Compare commits

...

131 Commits

Author SHA1 Message Date
jens 2361c758c9 store descriptions 2022-06-06 20:06:11 +02:00
jens f738e02b72 store descriptions 2022-06-06 02:47:51 +02:00
jens f5a3636222 intent pairs for sendBroadcast 2022-06-04 14:32:20 +02:00
jens bb1b3b0149 tethering detection 2022-06-04 02:44:26 +02:00
jens b35208b7aa tethering detection 2022-06-03 19:26:34 +02:00
jens b3ad72cc50 wifi receiver efficiency 2022-06-02 17:55:02 +02:00
jens c1809bd23c run executable action 2022-06-02 17:41:41 +02:00
jens 88a3ab8241 Merge remote-tracking branch 'origin/development' into development
# Conflicts:
#	app/src/main/java/com/jens/automation2/ActivityManageRule.java
2022-06-01 22:39:46 +02:00
jens 00f296d2d1 wifi action 2022-06-01 22:36:30 +02:00
jens e84842361c Merge remote-tracking branch 'origin/development-stable' into development 2022-05-29 22:30:16 +02:00
jens efaf0ed270 wifi toggle dialog reduced 2022-05-29 22:29:58 +02:00
jens 7167f0c03d run executable 2022-05-29 20:14:50 +02:00
jens a9673e65b9 crash when editing notification trigger 2022-05-29 15:13:30 +02:00
jens 592abe5b0d not contains comparator 2022-05-29 14:17:11 +02:00
jens dd7c3cb1d6 not contains comparator 2022-05-29 14:15:47 +02:00
jens 38665ccd92 Merge remote-tracking branch 'origin/development-stable' into development 2022-05-29 14:04:44 +02:00
jens c60347b990 syntax errors in translations fixed 2022-05-29 14:04:32 +02:00
jens 1e7ccf5200 not equals direction 2022-05-29 13:57:47 +02:00
jens 9b84b8dad7 translations 2022-05-29 13:38:57 +02:00
jens a19c84ea51 send broadcasts action 2022-05-29 02:42:12 +02:00
jens 3a14a56fd0 translations 2022-05-28 19:54:29 +02:00
jens 2dfc538343 screenstate no sec lock screen fixed 2022-05-27 20:21:13 +02:00
jens 67a58077cc time class changed 2022-05-26 18:47:30 +02:00
jens df68f7ca5c delayed lock screen 2022-05-26 18:26:49 +02:00
jens ad18313284 delayed lock screen 2022-05-26 15:50:39 +02:00
jens 29a93e0e43 language updates and screen locked trigger 2022-05-24 17:40:11 +02:00
jens a5d54c18d8 language updates and screen locked trigger 2022-05-24 17:31:25 +02:00
jens 62f5ad0005 operator change 2022-05-23 22:59:00 +02:00
jens 4eb7133d9d operator change 2022-05-23 22:45:54 +02:00
jens 343cbba8f8 broadcast trigger 2022-05-23 20:28:56 +02:00
jens 51caae0794 operator change 2022-05-22 23:07:05 +02:00
jens e39a2411ba broadcast trigger 2022-05-22 17:31:55 +02:00
jens 98b49036a7 Merge remote-tracking branch 'origin/development-stable' into development
# Conflicts:
#	app/src/main/res/values-de/strings.xml
#	app/src/main/res/values-es/strings.xml
#	app/src/main/res/values-it/strings.xml
#	app/src/main/res/values-nl/strings.xml
#	app/src/main/res/values/strings.xml
2022-05-21 14:08:19 +02:00
jens a7c4cc0965 app picker removed from play store version 2022-05-21 14:06:09 +02:00
jens 5d67452486 Merge remote-tracking branch 'origin/development-stable' into development
# Conflicts:
#	app/src/main/res/values-de/strings.xml
#	app/src/main/res/values-es/strings.xml
#	app/src/main/res/values-it/strings.xml
#	app/src/main/res/values-nl/strings.xml
#	app/src/main/res/values/strings.xml
2022-05-21 13:37:50 +02:00
jens 7e12a0f3e5 full day time window 2022-05-21 13:34:44 +02:00
jens 5786c1bfd4 full day time window 2022-05-21 02:33:56 +02:00
jens cf500c740e new release prep 2022-05-15 01:54:56 +02:00
jens 41efa7c11b Merge remote-tracking branch 'origin/development-stable' into development
# Conflicts:
#	app/src/main/res/values-de/strings.xml
#	app/src/main/res/values-es/strings.xml
#	app/src/main/res/values-it/strings.xml
#	app/src/main/res/values-nl/strings.xml
#	app/src/main/res/values/strings.xml
#	build.gradle
#	fastlane/metadata/android/en-US/changelogs/119.txt
2022-05-15 01:54:32 +02:00
jens 7046cccabe new release prep 2022-05-15 01:37:18 +02:00
jens bdbed3dbef app info text updated 2022-05-10 12:42:14 +02:00
jens 3f36c4c6b3 bug when picking app to start 2022-05-09 20:09:11 +02:00
jens 52a10fe626 bug when importing config while service is not running 2022-05-08 20:04:45 +02:00
jens 9fce7d987e bug when importing config while service is not running 2022-05-08 14:50:40 +02:00
jens d5ce04f80b wifi trigger, memorize most recent ssid 2022-05-07 02:06:17 +02:00
jens 62c97832a9 fix in DateTimeTrigger management and executions when service already stopped 2022-04-04 20:21:34 +02:00
jens 391edc59bf fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 20:25:10 +02:00
jens 0d3a13e753 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 16:20:20 +02:00
jens 152b0c3c49 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 14:46:28 +02:00
jens 7ed04c7ae2 cosmetics 2022-03-29 17:56:04 +02:00
jens c688a4c460 TimeFrame repetition fix 2022-03-26 20:00:50 +01:00
jens 5a09962cc9 TimeFrame repetition fix 2022-03-26 20:00:19 +01:00
jens 0368b2a8c8 v118 2022-03-13 16:06:10 +01:00
jens 965bf55811 Merge remote-tracking branch 'origin/development-stable' into development 2022-03-05 20:59:33 +01:00
jens 217f459833 nfc fix 2022-03-05 20:59:16 +01:00
jens 13fd4c2aae magnetometer 2022-03-05 02:00:16 +01:00
jens 195a60cfe0 magnetometer 2022-03-03 17:32:06 +01:00
jens 76563eb89b Merge remote-tracking branch 'origin/development-stable' into development 2022-02-28 13:46:42 +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 7733d57435 gradle 2022-02-26 13:02:07 +01:00
jens 481e4d1896 screen state string 2022-02-23 18:09:21 +01:00
jens 0bd64e4a53 operator change 2022-02-22 23:08:25 +01:00
jens 5af59e1754 Merge remote-tracking branch 'origin/development-stable' into development
# Conflicts:
#	app/src/main/java/com/jens/automation2/Trigger.java
2022-02-22 22:21:39 +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 619f348a28 Merge remote-tracking branch 'origin/development-stable' into development 2022-02-20 18:57:38 +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 9bf353ea3a logging 2022-02-12 20:04:19 +01:00
jens af90b566c8 new triggers: service or device starts 2022-02-07 20:09:45 +01:00
jens 0e51c577d5 new triggers: service or device starts 2022-02-06 20:12:11 +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 f3c4a0fd91 ringmode bug fixed 2022-01-14 19:28:33 +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 2a067507ae new release 1.7.2 2022-01-10 10:33:49 +01:00
jens 12f44aca8b notification action 2022-01-09 22:42:47 +01:00
jens 1c8eec735d code cleanups 2022-01-09 21:43:49 +01:00
jens 87edd595ba notification trigger 2022-01-09 15:22:03 +01:00
jens 53f46c10da translations 2022-01-09 14:55:52 +01:00
jens c5f04afe85 translations 2022-01-09 14:01:38 +01:00
jens 4d7fa711f9 profile trigger 2022-01-09 13:51:38 +01:00
jens 4bea2113fa profile trigger 2022-01-09 13:48:12 +01:00
jens 890260b8eb startApp 2022-01-08 19:00:06 +01:00
jens 230521149f startApp 2022-01-08 14:46:01 +01:00
jens 9a50da550a bugs and translations 2022-01-05 23:27:27 +01:00
jens 941bb3e1af profile trigger 2022-01-05 18:06:26 +01:00
jens 5653a9c70e profile trigger 2022-01-04 17:51:27 +01:00
jens 8c6331237d Cosmetics 2022-01-04 16:14:13 +01:00
jens 1bbf04d548 Exclusion from battery optimization 2022-01-03 23:24:34 +01:00
jens a2d93d27cb Cosmetics 2022-01-03 19:50:57 +01:00
136 changed files with 7999 additions and 2357 deletions
+11 -10
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 115
versionName "1.7.1"
versionCode 120
versionName "1.7.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -28,11 +28,6 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
flavorDimensions "version"
productFlavors
@@ -57,9 +52,15 @@ android {
targetSdkVersion 28
}
}
lint {
abortOnError false
checkReleaseBuilds false
}
namespace 'com.jens.automation2'
}
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": 115,
"versionName": "1.7.1-googlePlay",
"versionCode": 119,
"versionName": "1.7.5-googlePlay",
"outputFile": "app-googlePlayFlavor-release.apk"
}
],
+19 -11
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jens.automation2">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens
android:anyDensity="true"
@@ -65,6 +64,8 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<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"
@@ -72,6 +73,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"
@@ -121,15 +128,7 @@
<receiver android:name=".receivers.PackageReplacedReceiver"
android:enabled="true">
<intent-filter>
<!--<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.ACTION_PACKAGE_REPLACED" />-->
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--<data
android:path="com.jens.automation2"
android:scheme="package" />-->
</intent-filter>
</receiver>
<receiver android:name=".receivers.DateTimeListener" />
@@ -154,13 +153,22 @@
<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=".ActivityManageTriggerBroadcast" />
<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=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">
@@ -5,39 +5,40 @@ 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;
import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static ArrayList<Rule> ruleRunHistory = new ArrayList<Rule>();
public static ArrayList<Rule> getRuleRunHistory()
public static List<Rule> getRuleRunHistory()
{
return ruleRunHistory;
}
private ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet;
private String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution;
private static Date lastActivatedRuleActivationTime;
protected ArrayList<Trigger> triggerSet;
protected ArrayList<Action> actionSet;
protected String name;
protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
protected Calendar lastExecution;
protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution()
{
@@ -185,6 +186,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true))
{
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile();
if(returnValue)
@@ -233,20 +235,24 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection)
if(rule.getName().equals(this.getName()))
{
for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false;
}
if(this.getTriggerSet().size()==0)
}
}
if(this.getTriggerSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false;
}
if(this.getActionSet().size()==0)
if(this.getActionSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false;
@@ -312,19 +318,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:
@@ -341,6 +340,19 @@ public class Rule implements Comparable<Rule>
{
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution());
}
}
return false;
@@ -351,7 +363,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);
}
@@ -376,7 +391,8 @@ public class Rule implements Comparable<Rule>
if (!oneTrigger.applies(null, context))
return false;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format("Rule %1$s generally applies currently. Checking if it's really due, yet will be done separately.", this.getName()), 3);
return true;
}
@@ -433,7 +449,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 +457,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 +492,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 +551,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 +563,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 +638,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,31 +660,32 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
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.getTriggerType() == Trigger.Trigger_Enum.profileActive)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
String profileName = oneTrigger.getTriggerParameter2().split(triggerParameter2Split)[0];
if(profileName.equals(profile.getName()))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
break innerloop; //if the profile is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
}
public static ArrayList<Rule> findRuleCandidatesByProfile(Profile profile)
public static ArrayList<Rule> findRuleCandidatesByActionProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -907,4 +758,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;
}
}
+21 -12
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jens.automation2">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens
android:anyDensity="true"
@@ -51,6 +50,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />-->
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.NFC" />
@@ -62,6 +62,8 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<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"
@@ -69,6 +71,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"
@@ -118,15 +126,7 @@
<receiver android:name=".receivers.PackageReplacedReceiver"
android:enabled="true">
<intent-filter>
<!--<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.ACTION_PACKAGE_REPLACED" />-->
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--<data
android:path="com.jens.automation2"
android:scheme="package" />-->
</intent-filter>
</receiver>
<receiver android:name=".receivers.DateTimeListener" />
@@ -151,13 +151,22 @@
<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=".ActivityManageTriggerBroadcast" />
<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=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">
@@ -184,6 +193,7 @@
</intent-filter>
-->
<!--
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
@@ -217,7 +227,6 @@
<activity android:name=".ActivityPermissions" />
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
@@ -5,35 +5,37 @@ 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;
import java.sql.Time;
import com.jens.automation2.receivers.BroadcastListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static ArrayList<Rule> ruleRunHistory = new ArrayList<Rule>();
public static ArrayList<Rule> getRuleRunHistory()
public static List<Rule> getRuleRunHistory()
{
return ruleRunHistory;
}
private ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet;
private String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution;
private static Date lastActivatedRuleActivationTime;
protected ArrayList<Trigger> triggerSet;
protected ArrayList<Action> actionSet;
protected String name;
protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
protected Calendar lastExecution;
protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution()
{
@@ -44,7 +46,7 @@ public class Rule implements Comparable<Rule>
{
this.lastExecution = lastExecution;
}
public boolean isRuleToggle()
{
return ruleToggle;
@@ -181,6 +183,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true))
{
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile();
if(returnValue)
@@ -229,20 +232,24 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection)
if(rule.getName().equals(this.getName()))
{
for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false;
}
if(this.getTriggerSet().size()==0)
}
}
if(this.getTriggerSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false;
}
if(this.getActionSet().size()==0)
if(this.getActionSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false;
@@ -308,19 +315,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:
@@ -337,6 +337,19 @@ public class Rule implements Comparable<Rule>
{
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution());
}
}
return false;
@@ -347,7 +360,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);
}
@@ -372,7 +388,8 @@ public class Rule implements Comparable<Rule>
if (!oneTrigger.applies(null, context))
return false;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format("Rule %1$s generally applies currently. Checking if it's really due, yet will be done separately.", this.getName()), 3);
return true;
}
@@ -405,7 +422,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();
@@ -413,7 +430,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;
}
@@ -448,66 +465,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;
}
@@ -516,7 +524,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)
@@ -525,13 +536,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
}
}
}
@@ -580,186 +611,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>();
@@ -782,31 +633,32 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
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.getTriggerType() == Trigger.Trigger_Enum.profileActive)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
String profileName = oneTrigger.getTriggerParameter2().split(triggerParameter2Split)[0];
if(profileName.equals(profile.getName()))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
break innerloop; //if the profile is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
}
public static ArrayList<Rule> findRuleCandidatesByProfile(Profile profile)
public static ArrayList<Rule> findRuleCandidatesByActionProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -879,4 +731,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;
}
}
+12 -12
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jens.automation2">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens
android:anyDensity="true"
@@ -64,6 +63,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<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"/>
<application
android:allowBackup="true"
@@ -113,15 +113,7 @@
<receiver android:name=".receivers.PackageReplacedReceiver"
android:enabled="true">
<intent-filter>
<!--<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.ACTION_PACKAGE_REPLACED" />-->
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--<data
android:path="com.jens.automation2"
android:scheme="package" />-->
</intent-filter>
</receiver>
<receiver android:name=".receivers.DateTimeListener" />
@@ -146,13 +138,22 @@
<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=".ActivityManageTriggerBroadcast" />
<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=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">
@@ -213,7 +214,6 @@
<activity android:name=".ActivityPermissions" />
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
@@ -5,39 +5,40 @@ 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;
import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Rule implements Comparable<Rule>
{
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
protected static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
private static ArrayList<Rule> ruleRunHistory = new ArrayList<Rule>();
public static ArrayList<Rule> getRuleRunHistory()
public static List<Rule> getRuleRunHistory()
{
return ruleRunHistory;
}
private ArrayList<Trigger> triggerSet;
private ArrayList<Action> actionSet;
private String name;
private boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
private boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
private Calendar lastExecution;
private static Date lastActivatedRuleActivationTime;
protected ArrayList<Trigger> triggerSet;
protected ArrayList<Action> actionSet;
protected String name;
protected boolean ruleActive = true; // rules can be deactivated, so they won't fire if you don't want them temporarily
protected boolean ruleToggle = false; // rule will run again and do the opposite of its actions if applicable
protected Calendar lastExecution;
protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution()
{
@@ -185,6 +186,7 @@ public class Rule implements Comparable<Rule>
if(this.checkBeforeSaving(context, true))
{
Miscellaneous.logEvent("i", "Rule", "Changing rule: " + this.toString(), 3);
boolean returnValue = XmlFileInterface.writeFile();
if(returnValue)
@@ -233,20 +235,24 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
for(Rule rule : Rule.ruleCollection)
if(rule.getName().equals(this.getName()))
{
for (Rule rule : Rule.ruleCollection)
{
if (rule.getName().equals(this.getName()))
{
Toast.makeText(context, context.getResources().getString(R.string.anotherRuleByThatName), Toast.LENGTH_LONG).show();
return false;
}
if(this.getTriggerSet().size()==0)
}
}
if(this.getTriggerSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyTrigger), Toast.LENGTH_LONG).show();
return false;
}
if(this.getActionSet().size()==0)
if(this.getActionSet().size() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.pleaseSpecifiyAction), Toast.LENGTH_LONG).show();
return false;
@@ -312,19 +318,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:
@@ -341,6 +340,19 @@ public class Rule implements Comparable<Rule>
{
if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution())
return true;
/*
Workaround for repetition in TimeFrame triggers
*/
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
return oneTrigger.getTriggerParameter() == BroadcastListener.getInstance().hasBroadcastOccurredSince(oneTrigger.getTriggerParameter2(), getLastExecution());
}
}
return false;
@@ -351,7 +363,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);
}
@@ -376,7 +391,8 @@ public class Rule implements Comparable<Rule>
if (!oneTrigger.applies(null, context))
return false;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format("Rule %1$s generally applies currently. Checking if it's really due, yet will be done separately.", this.getName()), 3);
return true;
}
@@ -433,7 +449,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 +457,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 +492,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 +551,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 +563,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 +638,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,31 +660,32 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
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.getTriggerType() == Trigger.Trigger_Enum.profileActive)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
String profileName = oneTrigger.getTriggerParameter2().split(triggerParameter2Split)[0];
if(profileName.equals(profile.getName()))
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
break innerloop; //if the profile is found we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
}
public static ArrayList<Rule> findRuleCandidatesByProfile(Profile profile)
public static ArrayList<Rule> findRuleCandidatesByActionProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@@ -907,4 +758,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;
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jens.automation2">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+330 -218
View File
@@ -2,9 +2,12 @@ package com.jens.automation2;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
@@ -17,102 +20,118 @@ 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 {
setWifi,
setBluetooth,
setUsbTethering,
setWifiTethering,
setBluetoothTethering,
setDisplayRotation,
turnWifiOn,turnWifiOff,
turnBluetoothOn,turnBluetoothOff,
triggerUrl,
changeSoundProfile,
turnUsbTetheringOn,turnUsbTetheringOff,
turnWifiTetheringOn,turnWifiTetheringOff,
enableScreenRotation,disableScreenRotation,
startOtherActivity,
waitBeforeNextAction,
turnScreenOnOrOff,
setAirplaneMode,
setDataConnection,
speakText,
playMusic,
setScreenBrightness,
playSound,
vibrate,
sendTextMessage;
public String getFullName(Context context)
{
switch(this)
{
case setWifi:
return context.getResources().getString(R.string.actionSetWifi);
case setBluetooth:
return context.getResources().getString(R.string.actionSetBluetooth);
case setWifiTethering:
return context.getResources().getString(R.string.actionSetWifiTethering);
case setBluetoothTethering:
return context.getResources().getString(R.string.actionSetBluetoothTethering);
case setUsbTethering:
return context.getResources().getString(R.string.actionSetUsbTethering);
case setDisplayRotation:
return context.getResources().getString(R.string.actionSetDisplayRotation);
case turnWifiOn:
return context.getResources().getString(R.string.actionTurnWifiOn);
case turnWifiOff:
return context.getResources().getString(R.string.actionTurnWifiOff);
case turnBluetoothOn:
return context.getResources().getString(R.string.actionTurnBluetoothOn);
case turnBluetoothOff:
return context.getResources().getString(R.string.actionTurnBluetoothOff);
case triggerUrl:
return context.getResources().getString(R.string.actionTriggerUrl);
case changeSoundProfile:
return context.getResources().getString(R.string.actionChangeSoundProfile);
case turnUsbTetheringOn:
return context.getResources().getString(R.string.actionTurnUsbTetheringOn);
case turnUsbTetheringOff:
return context.getResources().getString(R.string.actionTurnUsbTetheringOff);
case turnWifiTetheringOn:
return context.getResources().getString(R.string.actionTurnWifiTetheringOn);
case turnWifiTetheringOff:
return context.getResources().getString(R.string.actionTurnWifiTetheringOff);
case enableScreenRotation:
return context.getResources().getString(R.string.actionEnableScreenRotation);
case disableScreenRotation:
return context.getResources().getString(R.string.actionDisableScreenRotation);
case startOtherActivity:
return context.getResources().getString(R.string.startOtherActivity);
case waitBeforeNextAction:
return context.getResources().getString(R.string.waitBeforeNextAction);
case turnScreenOnOrOff:
return context.getResources().getString(R.string.turnScreenOnOrOff);
case vibrate:
return context.getResources().getString(R.string.vibrate);
case setAirplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case setDataConnection:
return context.getResources().getString(R.string.actionDataConnection);
case speakText:
return context.getResources().getString(R.string.actionSpeakText);
case playMusic:
return context.getResources().getString(R.string.actionPlayMusic);
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);
default:
return "Unknown";
}
}
};
public enum Action_Enum
{
setWifi,
setBluetooth,
setUsbTethering,
setWifiTethering,
setBluetoothTethering,
setDisplayRotation,
turnWifiOn,turnWifiOff,
turnBluetoothOn,turnBluetoothOff,
triggerUrl,
changeSoundProfile,
turnUsbTetheringOn,turnUsbTetheringOff,
turnWifiTetheringOn,turnWifiTetheringOff,
enableScreenRotation,disableScreenRotation,
startOtherActivity,
waitBeforeNextAction,
turnScreenOnOrOff,
setAirplaneMode,
setDataConnection,
speakText,
playMusic,
controlMediaPlayback,
setScreenBrightness,
playSound,
vibrate,
createNotification,
closeNotification,
sendBroadcast,
runExecutable,
sendTextMessage;
public String getFullName(Context context)
{
switch(this)
{
case setWifi:
return context.getResources().getString(R.string.actionSetWifi);
case setBluetooth:
return context.getResources().getString(R.string.actionSetBluetooth);
case setWifiTethering:
return context.getResources().getString(R.string.actionSetWifiTethering);
case setBluetoothTethering:
return context.getResources().getString(R.string.actionSetBluetoothTethering);
case setUsbTethering:
return context.getResources().getString(R.string.actionSetUsbTethering);
case setDisplayRotation:
return context.getResources().getString(R.string.actionSetDisplayRotation);
case turnWifiOn:
return context.getResources().getString(R.string.actionTurnWifiOn);
case turnWifiOff:
return context.getResources().getString(R.string.actionTurnWifiOff);
case turnBluetoothOn:
return context.getResources().getString(R.string.actionTurnBluetoothOn);
case turnBluetoothOff:
return context.getResources().getString(R.string.actionTurnBluetoothOff);
case triggerUrl:
return context.getResources().getString(R.string.actionTriggerUrl);
case changeSoundProfile:
return context.getResources().getString(R.string.actionChangeSoundProfile);
case turnUsbTetheringOn:
return context.getResources().getString(R.string.actionTurnUsbTetheringOn);
case turnUsbTetheringOff:
return context.getResources().getString(R.string.actionTurnUsbTetheringOff);
case turnWifiTetheringOn:
return context.getResources().getString(R.string.actionTurnWifiTetheringOn);
case turnWifiTetheringOff:
return context.getResources().getString(R.string.actionTurnWifiTetheringOff);
case enableScreenRotation:
return context.getResources().getString(R.string.actionEnableScreenRotation);
case disableScreenRotation:
return context.getResources().getString(R.string.actionDisableScreenRotation);
case startOtherActivity:
return context.getResources().getString(R.string.startOtherActivity);
case waitBeforeNextAction:
return context.getResources().getString(R.string.waitBeforeNextAction);
case turnScreenOnOrOff:
return context.getResources().getString(R.string.turnScreenOnOrOff);
case vibrate:
return context.getResources().getString(R.string.vibrate);
case setAirplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case setDataConnection:
return context.getResources().getString(R.string.actionDataConnection);
case speakText:
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);
case sendBroadcast:
return context.getResources().getString(R.string.sendBroadcast);
case runExecutable:
return context.getResources().getString(R.string.runExecutable);
default:
return "Unknown";
}
}
};
private Action_Enum action;
private boolean parameter1 = false;
@@ -153,138 +172,209 @@ public class Action
public String toString()
{
StringBuilder returnString = new StringBuilder();
if(this.getAction().equals(Action_Enum.setWifi))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiOff));
}
else if(this.getAction().equals(Action_Enum.setBluetooth))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothOff));
}
else if(this.getAction().equals(Action_Enum.setUsbTethering))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnUsbTetheringOff));
}
else if(this.getAction().equals(Action_Enum.setWifiTethering))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnWifiTetheringOff));
}
else if(this.getAction().equals(Action_Enum.setBluetoothTethering))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnBluetoothTetheringOff));
}
else if(this.getAction().equals(Action_Enum.setDisplayRotation))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionEnableScreenRotation));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionDisableScreenRotation));
}
else if(this.getAction().equals(Action_Enum.setAirplaneMode))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTurnAirplaneModeOff));
}
else if(this.getAction().equals(Action_Enum.setDataConnection))
{
if(this.getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSetDataConnectionOff));
}
else if(this.getAction().equals(Action_Enum.startOtherActivity))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.startOtherActivity));
}
else if(this.getAction().equals(Action_Enum.triggerUrl))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionTriggerUrl));
}
else if(this.getAction().equals(Action_Enum.speakText))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionSpeakText));
}
else if(this.getAction().equals(Action_Enum.playMusic))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionPlayMusic));
}
else if(this.getAction().equals(Action_Enum.sendTextMessage))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendTextMessage));
}
else if(this.getAction().equals(Action_Enum.turnScreenOnOrOff))
{
if(getParameter1())
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOn));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.turnScreenOff));
}
else if(this.getAction().equals(Action_Enum.playSound))
{
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.playSound));
}
else
returnString.append(action.toString());
if(this.getAction().equals(Action_Enum.triggerUrl))
try
{
String[] components = parameter2.split(";");
if(components.length >= 3)
switch (getAction())
{
returnString.append(": " + components[2]);
if(parameter1)
returnString.append(" using authentication.");
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;
case sendBroadcast:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendBroadcast));
break;
case runExecutable:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.runExecutable));
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(" to number " + components[0]);
String[] components = parameter2.split(";");
if (components.length >= 3)
{
returnString.append(": " + components[2]);
returnString.append(". 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.setWifi))
{
if(!StringUtils.isEmpty(this.parameter2))
{
boolean useRoot = Boolean.parseBoolean(this.parameter2);
if(useRoot)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingRoot));
}
}
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(" 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();
}
@@ -363,7 +453,7 @@ public class Action
return (String[])actionTypesList.toArray(new String[actionTypesList.size()]);
}
public void run(Context context, boolean toggleActionIfPossible)
{
try
@@ -442,6 +532,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;
@@ -454,6 +547,25 @@ 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;
case sendBroadcast:
Actions.sendBroadcast(context, this.getParameter2());
break;
case runExecutable:
String[] execParts = this.getParameter2().split(Action.actionParameter2Split);
if(execParts.length == 1)
Actions.runExecutable(context, this.getParameter1(), execParts[0], null);
else if(execParts.length == 2)
Actions.runExecutable(context, this.getParameter1(), execParts[0], execParts[1]);
break;
default:
Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3);
break;
@@ -557,7 +669,7 @@ public class Action
//Do something with result
//Toast.makeText(context, text, duration) result;
Miscellaneous.logEvent("i", "HTTP RESULT", result, 3);
Actions myAction=new Actions();
Actions myAction = new Actions();
myAction.useDownloadedWebpage(result);
}
}
@@ -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;
@@ -46,7 +52,12 @@ import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.util.InetAddressUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -54,9 +65,13 @@ 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.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
@@ -64,9 +79,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,7 +93,124 @@ 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 class WifiStuff
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 void sendBroadcast(Context context, String action)
{
Miscellaneous.logEvent("i", "sendBroadcast", "Sending broadcast with action " + action, 5);
Intent broadcastIntent = new Intent();
if(action.contains(Action.actionParameter2Split))
{
String[] parts = action.split(Action.actionParameter2Split);
broadcastIntent.setAction(parts[0]);
add params
}
else
broadcastIntent.setAction(action);
context.sendBroadcast(broadcastIntent);
}
public static class WifiStuff
{
public static Boolean setWifi(Context context, Boolean desiredState, boolean toggleActionIfPossible)
{
@@ -120,7 +251,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 +825,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 +1061,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 +1141,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 +1205,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 +1332,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 +1446,7 @@ public class Actions
try
{
String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context);
autoMationServerRef.speak(textToSpeak, true);
automationServerRef.speak(textToSpeak, true);
}
catch (Exception e)
{
@@ -1345,23 +1476,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 +1492,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 +1644,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 +1657,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 +1670,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;
@@ -1770,4 +1924,187 @@ public class Actions
return android.provider.Settings.Global.getInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
}
public static boolean runExecutable(Context context, boolean runAsRoot, String path, String parameters)
{
if(runAsRoot)
{
if(!StringUtils.isEmpty(parameters))
return executeCommandViaSu(new String[] { path + " " + parameters });
else
return executeCommandViaSu(new String[] { path });
}
else
{
Object[] result;
File executable = new File(path);
File workingDir = new File(executable.getParent());
if(!StringUtils.isEmpty(parameters))
result = runExternalApplication(path, 0, workingDir, parameters);
else
result = runExternalApplication(path, 0, workingDir, null);
boolean execResult = (boolean) result[0];
return execResult;
}
}
/**
*
* @param commandToExecute
* @param timeout
* @param params
* @return Returns an array: 0=exit code, 1=cmdline output
*/
public static Object[] runExternalApplication(String commandToExecute, long timeout, File workingDirectory, String params)
{
/*
* Classes stolen from https://github.com/stleary/JSON-java
*/
String fullCommand;
if(!StringUtils.isEmpty(params))
fullCommand = commandToExecute + " " + params;
else
fullCommand = commandToExecute;
Miscellaneous.logEvent("i", "Running executable", "Running external application " + fullCommand, 4);
Object[] returnObject = new Object[2];
StringBuilder output = new StringBuilder();
String line = null;
OutputStream stdin = null;
InputStream stderr = null;
InputStream stdout = null;
try
{
Process process = null;
if(workingDirectory != null)
process = Runtime.getRuntime().exec(fullCommand, null, workingDirectory);
else
process = Runtime.getRuntime().exec(fullCommand);
stdin = process.getOutputStream ();
stderr = process.getErrorStream ();
stdout = process.getInputStream ();
// "write" the parms into stdin
/*line = "param1" + "\n";
stdin.write(line.getBytes() );
stdin.flush();
line = "param2" + "\n";
stdin.write(line.getBytes() );
stdin.flush();
line = "param3" + "\n";
stdin.write(line.getBytes() );
stdin.flush();*/
stdin.close();
// clean up if any output in stdout
BufferedReader brCleanUp = new BufferedReader (new InputStreamReader (stdout));
while ((line = brCleanUp.readLine ()) != null)
{
Miscellaneous.logEvent ("i", "Running executable", "[Stdout] " + line, 4);
output.append(line);
}
brCleanUp.close();
// clean up if any output in stderr
brCleanUp = new BufferedReader (new InputStreamReader(stderr));
while ((line = brCleanUp.readLine ()) != null)
{
Miscellaneous.logEvent ("i", "Running executable", "[Stderr] " + line, 4);
output.append(line);
}
brCleanUp.close();
try
{
// Wait for the process to exit, we want the return code
if(timeout > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
try
{
if(!process.waitFor(timeout, TimeUnit.MILLISECONDS))
{
Miscellaneous.logEvent("i", "Running executable", "Timeout of " + String.valueOf(timeout) + " ms reached. Killing check attempt.", 3);
process.destroyForcibly();
}
}
catch(NoSuchMethodError e)
{
process.waitFor();
}
}
else
process.waitFor();
}
catch (InterruptedException e)
{
Miscellaneous.logEvent("i", "Running executable", "Waiting for process failed: " + Log.getStackTraceString(e), 4);
Miscellaneous.logEvent("i", "Running executable", Log.getStackTraceString(e), 1);
}
if(process.exitValue() == 0)
Miscellaneous.logEvent("i", "Running executable", "ReturnCode: " + String.valueOf(process.exitValue()), 4);
else
Miscellaneous.logEvent("i", "Running executable", "External execution (RC=" + String.valueOf(process.exitValue()) + ") returned error: " + output.toString(), 3);
returnObject[0] = process.exitValue();
returnObject[1] = output.toString();
return returnObject;
}
catch (IOException e)
{
Miscellaneous.logEvent("e", "Running executable", Log.getStackTraceString(e), 1);
}
Miscellaneous.logEvent("i", "Running executable", "Error running external application.", 1);
// if(slotMap != null)
// for(String key : slotMap.keySet())
// System.clearProperty(key);
return null;
}
public static boolean isTetheringActive1(Context context)
{
try
{
for(Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();)
{
NetworkInterface intf = en.nextElement();
for(Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
{
InetAddress inetAddress = enumIpAddr.nextElement();
if(!intf.isLoopback())
{
if(intf.getName().contains("rndis"))
{
return true;
}
}
}
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "isTetheringActive()", Log.getStackTraceString(e), 3);
}
return false;
}
}
@@ -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,23 @@ 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);
AutomationService service = AutomationService.getInstance();
if(service != null && service.isRunning)
service.applySettingsAndRules();
}
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 +266,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 +310,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();
@@ -331,13 +346,37 @@ public class ActivityMaintenance extends Activity
public static String getSystemInfo()
{
StringBuilder systemInfoText = new StringBuilder();
systemInfoText.append("App details" + Miscellaneous.lineSeparator);
systemInfoText.append("Version name: " + BuildConfig.VERSION_NAME + Miscellaneous.lineSeparator);
systemInfoText.append("Version code: " + BuildConfig.VERSION_CODE + Miscellaneous.lineSeparator);
systemInfoText.append("Flavor: " + BuildConfig.FLAVOR + Miscellaneous.lineSeparator);
systemInfoText.append("Device details" + Miscellaneous.lineSeparator);
systemInfoText.append("OS version: " + System.getProperty("os.version") + Miscellaneous.lineSeparator);
systemInfoText.append("API Level: " + android.os.Build.VERSION.SDK + Miscellaneous.lineSeparator);
systemInfoText.append("Target SDK: " + Miscellaneous.getAnyContext().getApplicationInfo().targetSdkVersion + Miscellaneous.lineSeparator);
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("Rooted: " + String.valueOf(Miscellaneous.isPhoneRooted()) + Miscellaneous.lineSeparator);
systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator);
systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName() + Miscellaneous.lineSeparator);
systemInfoText.append("Logfile written: " + String.valueOf(Settings.writeLogFile) + Miscellaneous.lineSeparator);
systemInfoText.append("Log level: " + String.valueOf(Settings.logLevel));
/*
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 +406,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();
}
}
@@ -184,8 +184,16 @@ public class ActivityMainProfiles extends ActivityGeneric
startActivityForResult(manageSpecificProfileIntent, 2000);
break;
case 2:
if(profile.delete(myAutomationService))
updateListView();
Rule user = profile.isInUseByRules();
if(user == null)
{
if (profile.delete(ActivityMainProfiles.this))
updateListView();
else
Toast.makeText(ActivityMainProfiles.this, getResources().getString(R.string.profileCouldNotBeDeleted), Toast.LENGTH_LONG).show();
}
else
Toast.makeText(ActivityMainProfiles.this, String.format(getResources().getString(R.string.ruleXIsUsingProfileY), user.getName(), profile.getName()), Toast.LENGTH_LONG).show();
break;
}
}
@@ -25,6 +25,7 @@ import java.util.ArrayList;
public class ActivityMainRules extends ActivityGeneric
{
public static final String intentNameRuleName = "ruleName";
private ListView ruleListView;
ArrayList<Rule> ruleList = new ArrayList<>();
private ArrayAdapter<Rule> ruleListViewAdapter;
@@ -135,7 +136,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 +200,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;
}
@@ -206,8 +208,8 @@ public class ActivityMainRules extends ActivityGeneric
Toast.makeText(ActivityMainRules.this, getResources().getString(R.string.serviceHasToRunForThat), Toast.LENGTH_LONG).show();
break;
case 1:
ruleToEdit = ruleThisIsAbout;
Intent manageSpecificRuleIntent = new Intent (ActivityMainRules.this, ActivityManageRule.class);
manageSpecificRuleIntent.putExtra(intentNameRuleName, ruleThisIsAbout.getName());
startActivityForResult(manageSpecificRuleIntent, requestCodeChangeRule);
break;
case 2:
@@ -250,15 +252,5 @@ public class ActivityMainRules extends ActivityGeneric
}
catch(NullPointerException e)
{}
try
{
if(AutomationService.isMyServiceRunning(this))
DateTimeListener.reloadAlarms();
}
catch(NullPointerException e)
{
// AlarmManager instance not prepared, yet.
}
}
}
@@ -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,18 +68,18 @@ 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);
bDonate = (Button)findViewById(R.id.bDonate);
if(!BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor"))
if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))
bDonate.setVisibility(View.VISIBLE);
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
@@ -99,7 +93,8 @@ public class ActivityMainScreen extends ActivityGeneric
if (toggleService.isChecked())
{
startAutomationService(getBaseContext(), false);
} else
}
else
{
stopAutomationService();
}
@@ -147,13 +142,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 +365,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 +383,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 +401,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,393 @@
package com.jens.automation2;
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.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;
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.directionStringDoesNotContain),
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();
}
});
}
}
@@ -0,0 +1,114 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
public class ActivityManageActionRunExecutable extends Activity
{
final static int PICKFILE_RESULT_CODE = 4711;
CheckBox chkRunExecAsRoot;
EditText etRunExecutablePath, etRunExecutableParameters;
Button bChooseExecutable, bSaveActionRunExec;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_run_executable);
chkRunExecAsRoot = (CheckBox)findViewById(R.id.chkRunExecAsRoot);
etRunExecutablePath = (EditText) findViewById(R.id.etRunExecutablePath);
etRunExecutableParameters = (EditText) findViewById(R.id.etRunExecutableParameters);
bChooseExecutable = (Button) findViewById(R.id.bChooseExecutable);
bSaveActionRunExec = (Button) findViewById(R.id.bSaveActionRunExec);
bChooseExecutable.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//Need to check for storage permissions
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
chooseFile = Intent.createChooser(chooseFile, getResources().getString(R.string.selectSoundFile));
startActivityForResult(chooseFile, PICKFILE_RESULT_CODE);
}
});
bSaveActionRunExec.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
saveExecSettings();
}
});
}
void saveExecSettings()
{
if(etRunExecutablePath.getText().toString() == null || etRunExecutablePath.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.selectValidExecutable), Toast.LENGTH_LONG).show();
return;
}
else
{
File executableFile = new File(etRunExecutablePath.getText().toString());
if(!executableFile.exists())
{
Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.fileDoesNotExist), Toast.LENGTH_LONG).show();
return;
}
else
{
if(!chkRunExecAsRoot.isChecked() && !executableFile.canExecute())
{
Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.fileNotExecutable), Toast.LENGTH_LONG).show();
return;
}
}
}
Intent returnData = new Intent();
returnData.putExtra(ActivityManageRule.intentNameActionParameter1, chkRunExecAsRoot.isChecked());
if(etRunExecutableParameters.getText() != null && !StringUtils.isEmpty(etRunExecutableParameters.getText().toString()))
returnData.putExtra(ActivityManageRule.intentNameActionParameter2, etRunExecutablePath.getText().toString() + Action.actionParameter2Split + etRunExecutableParameters.getText().toString());
else
returnData.putExtra(ActivityManageRule.intentNameActionParameter2, etRunExecutablePath.getText().toString());
setResult(RESULT_OK, returnData);
finish();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK)
{
if(requestCode == PICKFILE_RESULT_CODE)
{
Uri fileUri = data.getData();
String filePath = CompensateCrappyAndroidPaths.getPath(ActivityManageActionRunExecutable.this, fileUri);
etRunExecutablePath.setText(filePath);
}
}
}
}
@@ -0,0 +1,256 @@
package com.jens.automation2;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class ActivityManageActionSendBroadcast extends Activity
{
EditText etBroadcastToSend;
Button bBroadcastSendShowSuggestions, bSaveSendBroadcast, bAddIntentPair;
ListView lvIntentPairs;
EditText etParameterName, etParameterValue;
Spinner spinnerParameterType;
ArrayAdapter<String> intentTypeSpinnerAdapter, intentPairAdapter;
private static final String[] supportedIntentTypes = { "boolean", "byte", "char", "double", "float", "int", "long", "short", "String", "Uri" };
private ArrayList<String> intentPairList = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_send_broadcast);
etBroadcastToSend = (EditText)findViewById(R.id.etBroadcastToSend);
bBroadcastSendShowSuggestions = (Button)findViewById(R.id.bBroadcastSendShowSuggestions);
bSaveSendBroadcast = (Button)findViewById(R.id.bSaveSendBroadcast);
bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair);
lvIntentPairs = (ListView) findViewById(R.id.lvIntentPairs);
etParameterName = (EditText) findViewById(R.id.etParameterName);
etParameterValue = (EditText) findViewById(R.id.etParameterValue);
spinnerParameterType = (Spinner) findViewById(R.id.spinnerParameterType);
intentTypeSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionSendBroadcast.supportedIntentTypes);
spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
intentTypeSpinnerAdapter.notifyDataSetChanged();
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
bSaveSendBroadcast.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
if(checkInput())
{
Intent answer = new Intent();
String param2 = etBroadcastToSend.getText().toString();
if(intentPairList.size() > 0)
{
param2 += Action.actionParameter2Split;
for (String s : intentPairList)
param2 += s + ";";
param2 = param2.substring(0, param2.length() - 1);
}
answer.putExtra(ActivityManageRule.intentNameActionParameter2, param2);
setResult(RESULT_OK, answer);
finish();
}
}
});
bBroadcastSendShowSuggestions.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ActivityManageActionSendBroadcast.this);
builder.setTitle(getResources().getString(R.string.selectBroadcast));
builder.setItems(ActivityManageTriggerBroadcast.broadcastSuggestions, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialogInterface, int which)
{
etBroadcastToSend.setText(ActivityManageTriggerBroadcast.broadcastSuggestions[which]);
}
});
builder.create().show();
}
});
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameActionParameter2))
{
String param2 = input.getStringExtra(ActivityManageRule.intentNameActionParameter2);
if(!param2.contains(Action.actionParameter2Split))
etBroadcastToSend.setText(input.getStringExtra(ActivityManageRule.intentNameActionParameter2));
else
{
String[] param2Parts = param2.split(Action.actionParameter2Split);
etBroadcastToSend.setText(param2Parts[0]);
String[] params = param2Parts[1].split(";");
intentPairList.clear();
for(int i = 0; i < params.length; i++)
{
if(lvIntentPairs.getVisibility() != View.VISIBLE)
lvIntentPairs.setVisibility(View.VISIBLE);
intentPairList.add(params[i]);
}
updateIntentPairList();
}
}
bAddIntentPair.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
// type;name;value
if(spinnerParameterType.getSelectedItem().toString().length() == 0)
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show();
return;
}
if(etParameterName.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
if(etParameterValue.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
spinnerParameterType.setSelection(0);
etParameterName.setText("");
etParameterValue.setText("");
updateIntentPairList();
if(lvIntentPairs.getVisibility() != View.VISIBLE)
lvIntentPairs.setVisibility(View.VISIBLE);
}
});
lvIntentPairs.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
getIntentPairDialog(arg2).show();
return false;
}
});
spinnerParameterType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
else
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
}
boolean checkInput()
{
String broadcastToSend = etBroadcastToSend.getText().toString();
if(StringUtils.isEmpty(broadcastToSend))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enterBroadcast), Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
private void updateIntentPairList()
{
if(lvIntentPairs.getAdapter() == null)
lvIntentPairs.setAdapter(intentPairAdapter);
intentPairAdapter.notifyDataSetChanged();
}
private AlertDialog getIntentPairDialog(final int itemPosition)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ActivityManageActionSendBroadcast.this);
alertDialogBuilder.setTitle(getResources().getString(R.string.whatToDoWithIntentPair));
alertDialogBuilder.setItems(new String[]{getResources().getString(R.string.delete)}, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// Only 1 choice at the moment, no need to check
ActivityManageActionSendBroadcast.this.intentPairList.remove(itemPosition);
updateIntentPairList();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
}
@@ -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)
{
@@ -15,8 +15,6 @@ public class ActivityManageActionSpeakText extends Activity
private Button bSaveSpeakText;
private EditText etSpeakText;
// private String existingUrl = "";
public static boolean edit = false;
public static Action resultingAction = null;
@@ -27,7 +25,7 @@ public class ActivityManageActionSpeakText extends Activity
this.setContentView(R.layout.activity_manage_action_speak_text);
etSpeakText = (EditText)findViewById(R.id.etTextToSpeak);
bSaveSpeakText = (Button)findViewById(R.id.bSaveTriggerUrl);
bSaveSpeakText = (Button)findViewById(R.id.bSaveSpeakText);
bSaveSpeakText.setOnClickListener(new OnClickListener()
{
@Override
@@ -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,204 @@ 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;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_start_activity);
lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs);
etParameterName = (EditText)findViewById(R.id.etParameterName);
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair);
bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity);
spinnerParameterType = (Spinner)findViewById(R.id.spinnerParameterType);
etPackageName = (EditText) findViewById(R.id.etPackageName);
etActivityOrActionPath = (EditText) findViewById(R.id.etActivityOrActionPath);
rbStartAppSelectByActivity = (RadioButton)findViewById(R.id.rbStartAppSelectByActivity);
rbStartAppSelectByAction = (RadioButton)findViewById(R.id.rbStartAppSelectByAction);
showStartProgramExamples = (Button)findViewById(R.id.showStartProgramExamples);
rbStartAppByActivity = (RadioButton)findViewById(R.id.rbStartAppByActivity);
rbStartAppByBroadcast = (RadioButton)findViewById(R.id.rbStartAppByBroadcast);
intentTypeSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionStartActivity.supportedIntentTypes);
spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
intentTypeSpinnerAdapter.notifyDataSetChanged();
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
bSelectApp.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && targetSdkVersion >= 30 && !ActivityPermissions.havePermission(Manifest.permission.QUERY_ALL_PACKAGES, ActivityManageActionStartActivity.this))// && shouldShowRequestPermissionRationale(Manifest.permission.QUERY_ALL_PACKAGES))
{
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
{
// This ain't possible anymore.
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.featureNotInGooglePlayVersion) + Miscellaneous.lineSeparator + Miscellaneous.lineSeparator + getResources().getString(R.string.startActivityInsertManually), ActivityManageActionStartActivity.this).show();
}
else
requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission);
}
else
getAppList();
}
});
bAddIntentPair.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// type;name;value
if(spinnerParameterType.getSelectedItem().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show();
return;
}
if(etParameterName.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
if(etParameterValue.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
spinnerParameterType.setSelection(0);
etParameterName.setText("");
etParameterValue.setText("");
updateIntentPairList();
if(lvIntentPairs.getVisibility() != View.VISIBLE)
lvIntentPairs.setVisibility(View.VISIBLE);
}
});
showStartProgramExamples.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlShowExamples));
startActivity(browserIntent);
}
});
lvIntentPairs.setOnItemLongClickListener(new OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
getIntentPairDialog(arg2).show();
return false;
}
});
bSaveActionStartOtherActivity.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if(saveAction())
{
ActivityManageActionStartActivity.this.setResult(RESULT_OK);
finish();
}
}
});
lvIntentPairs.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
spinnerParameterType.setOnItemSelectedListener(new OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
else
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
rbStartAppSelectByActivity.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
bSelectApp.setEnabled(isChecked);
}
});
rbStartAppSelectByAction.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
bSelectApp.setEnabled(!isChecked);
}
});
Intent i = getIntent();
if(i.getBooleanExtra("edit", false) == true)
{
edit = true;
loadValuesIntoGui();
}
}
private class CustomPackageInfo extends PackageInfo implements Comparable<CustomPackageInfo>
{
@@ -76,7 +278,6 @@ public class ActivityManageActionStartActivity extends Activity
return name1.compareTo(name2);
}
}
private static List<PackageInfo> pInfos = null;
@@ -230,44 +431,89 @@ public class ActivityManageActionStartActivity extends Activity
return null;
}
private AlertDialog getActionStartActivityDialog1()
private AlertDialog getActionStartActivityDialog1Application()
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectApplication));
final String[] applicationArray = ActivityManageActionStartActivity.getApplicationNameListString(this);
alertDialogBuilder.setItems(applicationArray, new DialogInterface.OnClickListener()
{
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
getActionStartActivityDialog2(applicationArray[which]).show();
getActionStartActivityDialog2(applicationArray[which]);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private AlertDialog getActionStartActivityDialog2(String applicationName)
private void getActionStartActivityDialog2(String applicationName)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectPackageOfApplication));
final String[] packageArray = ActivityManageActionStartActivity.getPackageListString(this, applicationName);
alertDialogBuilder.setItems(packageArray, new DialogInterface.OnClickListener()
{
if(packageArray.length > 1)
{
alertDialogBuilder.setItems(packageArray, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
getActionStartActivityDialog4ActivityPickMethod(packageArray[which]).show();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
else
{
getActionStartActivityDialog4ActivityPickMethod(packageArray[0]).show();
}
}
private AlertDialog getActionStartActivityDialog4ActivityPickMethod(final String packageName)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(getResources().getString(R.string.launcherOrManualExplanation));
alertDialogBuilder.setPositiveButton(getResources().getString(R.string.takeLauncherActivity), 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), ActivityManageActionStartActivity.this).show();
// Pick the launcher automatically
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(packageName);
if (launchIntent != null)
{
ActivityInfo ai = ActivityManageActionStartActivity.getActivityInfoForPackageNameAndActivityName(packageName, launchIntent.getComponent().getClassName());
etPackageName.setText(ai.packageName);
etActivityOrActionPath.setText(ai.name);
}
else
{
getActionStartActivityDialog5Activity(packageName).show();
Miscellaneous.messageBox(getResources().getString(R.string.hint), getResources().getString(R.string.launcherNotFound) + Miscellaneous.lineSeparator + getResources().getString(R.string.chooseActivityHint), ActivityManageActionStartActivity.this).show();
}
}
});
alertDialogBuilder.setNegativeButton(getResources().getString(R.string.pickActivityManually), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
getActionStartActivityDialog5Activity(packageName).show();
Miscellaneous.messageBox(getResources().getString(R.string.hint), getResources().getString(R.string.chooseActivityHint), ActivityManageActionStartActivity.this).show();
}
});
final String activityArray[] = ActivityManageActionStartActivity.getActivityListForPackageName(packageName);
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private AlertDialog getActionStartActivityDialog3(final String packageName)
private AlertDialog getActionStartActivityDialog5Activity(final String packageName)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectActivityToBeStarted));
@@ -283,195 +529,14 @@ public class ActivityManageActionStartActivity extends Activity
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
@Override
protected void onCreate(Bundle savedInstanceState)
void getAppList()
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_start_activity);
lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs);
etParameterName = (EditText)findViewById(R.id.etParameterName);
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair);
bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity);
spinnerParameterType = (Spinner)findViewById(R.id.spinnerParameterType);
etPackageName = (EditText) findViewById(R.id.etPackageName);
etActivityOrActionPath = (EditText) findViewById(R.id.etActivityOrActionPath);
rbStartAppSelectByActivity = (RadioButton)findViewById(R.id.rbStartAppSelectByActivity);
rbStartAppSelectByAction = (RadioButton)findViewById(R.id.rbStartAppSelectByAction);
showStartProgramExamples = (Button)findViewById(R.id.showStartProgramExamples);
rbStartAppByActivity = (RadioButton)findViewById(R.id.rbStartAppByActivity);
rbStartAppByBroadcast = (RadioButton)findViewById(R.id.rbStartAppByBroadcast);
intentTypeSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionStartActivity.supportedIntentTypes);
spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
intentTypeSpinnerAdapter.notifyDataSetChanged();
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
bSelectApp.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
}
});
bAddIntentPair.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// type;name;value
if(spinnerParameterType.getSelectedItem().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show();
return;
}
if(etParameterName.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(Action.intentPairSeperator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterName.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
if(etParameterValue.getText().toString().length() == 0)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(Action.intentPairSeperator))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show();
return;
}
else if(etParameterValue.getText().toString().contains(";"))
{
Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show();
return;
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeperator + etParameterName.getText().toString() + Action.intentPairSeperator + etParameterValue.getText().toString();
intentPairList.add(param);
spinnerParameterType.setSelection(0);
etParameterName.setText("");
etParameterValue.setText("");
updateIntentPairList();
if(lvIntentPairs.getVisibility() != View.VISIBLE)
lvIntentPairs.setVisibility(View.VISIBLE);
}
});
showStartProgramExamples.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlShowExamples));
startActivity(browserIntent);
}
});
lvIntentPairs.setOnItemLongClickListener(new OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
getIntentPairDialog(arg2).show();
return false;
}
});
bSaveActionStartOtherActivity.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if(saveAction())
{
ActivityManageActionStartActivity.this.setResult(RESULT_OK);
finish();
}
}
});
lvIntentPairs.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
spinnerParameterType.setOnItemSelectedListener(new OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
else
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
rbStartAppSelectByActivity.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
bSelectApp.setEnabled(isChecked);
}
});
rbStartAppSelectByAction.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
bSelectApp.setEnabled(!isChecked);
}
});
Intent i = getIntent();
if(i.getBooleanExtra("edit", false) == true)
{
edit = true;
loadValuesIntoGui();
}
GetActivityListTask getActivityListTask = new GetActivityListTask();
getActivityListTask.execute();
progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications));
}
private void loadValuesIntoGui()
@@ -598,7 +663,6 @@ public class ActivityManageActionStartActivity extends Activity
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
@@ -615,9 +679,25 @@ public class ActivityManageActionStartActivity extends Activity
protected void onPostExecute(Void result)
{
progressDialog.dismiss();
getActionStartActivityDialog1().show();
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;
}
}
}
}
}
@@ -47,7 +47,7 @@ public class ActivityManageActionTriggerUrl extends Activity
chkTriggerUrlUseAuthentication = (CheckBox)findViewById(R.id.chkTriggerUrlUseAuthentication);
lvTriggerUrlPostParameters = (ListView)findViewById(R.id.lvTriggerUrlPostParameters);
tlTriggerUrlAuthentication = (TableLayout)findViewById(R.id.tlTriggerUrlAuthentication);
bSaveTriggerUrl = (Button)findViewById(R.id.bSaveTriggerUrl);
bSaveTriggerUrl = (Button)findViewById(R.id.bSaveSpeakText);
bSaveTriggerUrl.setOnClickListener(new OnClickListener()
{
@Override
@@ -0,0 +1,63 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.annotation.Nullable;
public class ActivityManageActionWifi extends Activity
{
CheckBox chkWifiRunAsRoot;
RadioButton rbActionWifiOn, rbActionWifiOff;
Button bActionWifiSave;
TextView tvWifiExplanation1, tvWifiExplanation2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_wifi);
chkWifiRunAsRoot = (CheckBox)findViewById(R.id.chkWifiRunAsRoot);
rbActionWifiOn = (RadioButton) findViewById(R.id.rbActionWifiOn);
rbActionWifiOff = (RadioButton)findViewById(R.id.rbActionWifiOff);
bActionWifiSave = (Button) findViewById(R.id.bActionWifiSave);
tvWifiExplanation1 = (TextView)findViewById(R.id.tvWifiExplanation1);
tvWifiExplanation2 = (TextView)findViewById(R.id.tvWifiExplanation2);
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameActionParameter1))
rbActionWifiOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true));
if(input.hasExtra(ActivityManageRule.intentNameActionParameter2))
chkWifiRunAsRoot.setChecked(Boolean.parseBoolean(input.getStringExtra(ActivityManageRule.intentNameActionParameter2)));
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
// Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android10WifiToggleNotice), ActivityManageActionWifi.this).show();
if(getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q)
tvWifiExplanation1.setVisibility(View.VISIBLE);
else
tvWifiExplanation1.setVisibility(View.GONE);
bActionWifiSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameActionParameter1, rbActionWifiOn.isChecked());
response.putExtra(ActivityManageRule.intentNameActionParameter2, String.valueOf(chkWifiRunAsRoot.isChecked()));
setResult(RESULT_OK, response);
finish();
}
});
}
}
@@ -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;
@@ -33,7 +34,6 @@ public class ActivityManagePoi extends Activity
public LocationManager myLocationManager;
MyLocationListenerGps myLocationListenerGps = new MyLocationListenerGps();
Location locationGps = null, locationNetwork = null;
// Location locationWifi = null;
MyLocationListenerNetwork myLocationListenerNetwork = new MyLocationListenerNetwork();
Button bGetPosition, bSavePoi;
ImageButton ibShowOnMap;
@@ -83,17 +83,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 +136,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 +313,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()
@@ -3,7 +3,6 @@ package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -14,6 +13,7 @@ import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.text.util.Linkify;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@@ -50,34 +50,33 @@ public class ActivityManageRule extends Activity
{
final static String activityDetectionClassPath = "com.jens.automation2.receivers.ActivityDetectionReceiver";
public final static String intentNameTriggerParameter1 = "triggerParameter1";
public final static String intentNameTriggerParameter2 = "triggerParameter2";
public final static String intentNameActionParameter1 = "actionParameter1";
public final static String intentNameActionParameter2 = "actionParameter2";
public Context context;
private Button cmdTriggerAdd, cmdActionAdd, cmdSaveRule;
private ListView triggerListView, actionListView;
private EditText etRuleName;
private CheckBox chkRuleActive, chkRuleToggle;
private static ActivityManageRule instance = null;
Button cmdTriggerAdd, cmdActionAdd, cmdSaveRule;
ListView triggerListView, actionListView;
EditText etRuleName;
CheckBox chkRuleActive, chkRuleToggle;
static ActivityManageRule instance = null;
ImageView imageHelpButton;
private static ProgressDialog progressDialog = null;
static ProgressDialog progressDialog = null;
private static Trigger_Enum triggerType;
private static boolean triggerParameter;
private static PointOfInterest triggerPoi;
private static String triggerProcess;
private static int triggerBattery;
private static double triggerSpeed;
private static double triggerNoise;
private static TimeFrame triggerTimeFrame;
private static String triggerWifiName;
static Trigger_Enum triggerType;
static PointOfInterest triggerPoi;
static String triggerProcess;
static int triggerBattery;
static double triggerSpeed;
static double triggerNoise;
static boolean newRule;
private static Rule ruleToEdit;
private static boolean newRule;
static Trigger newTrigger;
static Action newAction;
private static Trigger newTrigger;
private static Action newAction;
Rule ruleToEdit = null;
ArrayAdapter<Trigger> triggerListViewAdapter;
ArrayAdapter<Action> actionListViewAdapter;
@@ -101,18 +100,36 @@ 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;
final static int requestCodeTriggerPhoneCallEdit = 602;
final static int requestCodeTriggerProfileAdd = 603;
final static int requestCodeTriggerProfileEdit = 604;
final static int requestCodeTriggerWifiAdd = 723;
final static int requestCodeTriggerWifiEdit = 724;
final static int requestCodeActionSendTextMessageAdd = 5001;
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;
final static int requestCodeTriggerBroadcastReceivedAdd = 809;
final static int requestCodeTriggerBroadcastReceivedEdit = 810;
final static int requestCodeActionSendBroadcastAdd = 811;
final static int requestCodeActionSendBroadcastEdit = 812;
final static int requestCodeActionRunExecutableAdd = 813;
final static int requestCodeActionRunExecutableEdit = 814;
final static int requestCodeActionSetWifiAdd = 815;
final static int requestCodeActionSetWifiEdit = 816;
final static int requestCodeTriggerTetheringAdd = 817;
final static int requestCodeTriggerTetheringEdit = 818;
public static ActivityManageRule getInstance()
{
if(instance == null)
@@ -124,10 +141,10 @@ public class ActivityManageRule extends Activity
@Override
protected void onCreate(Bundle savedInstanceState)
{
context = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_specific_rule);
context = this;
instance = this;
cmdTriggerAdd = (Button)findViewById(R.id.cmdTriggerAdd);
@@ -141,7 +158,17 @@ public class ActivityManageRule extends Activity
imageHelpButton = (ImageView)findViewById(R.id.imageHelpButton);
//decide if it will be created anew or loaded to edit an existing one
if(ActivityMainRules.ruleToEdit == null)
if(getIntent().hasExtra(ActivityMainRules.intentNameRuleName))
{
// change existing rule
Miscellaneous.logEvent("i", "Rule", "Cache not empty, assuming change request.", 3);
newRule = false;
ruleToEdit = Rule.getByName(getIntent().getStringExtra(ActivityMainRules.intentNameRuleName));
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
loadVariablesIntoGui();
}
else
{
// new rule
Miscellaneous.logEvent("i", "Rule", "Cache empty, assuming create request.", 3);
@@ -152,16 +179,6 @@ public class ActivityManageRule extends Activity
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
}
else
{
// change existing rule
Miscellaneous.logEvent("i", "Rule", "Cache not empty, assuming change request.", 3);
newRule = false;
ruleToEdit = ActivityMainRules.ruleToEdit;
triggerListViewAdapter = new ArrayAdapter<Trigger>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getTriggerSet());
actionListViewAdapter = new ArrayAdapter<Action>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ruleToEdit.getActionSet());
loadVariablesIntoGui();
}
cmdTriggerAdd.setOnClickListener(new OnClickListener()
{
@@ -250,8 +267,9 @@ public class ActivityManageRule extends Activity
switch(selectedTrigger.getTriggerType())
{
case timeFrame:
ActivityManageTriggerTimeFrame.editedTimeFrameTrigger = selectedTrigger;
Intent timeFrameEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTimeFrame.class);
timeFrameEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
timeFrameEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeEdit);
break;
case bluetoothConnection:
@@ -263,7 +281,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;
@@ -271,11 +289,17 @@ public class ActivityManageRule extends Activity
phoneCallEditor.putExtra("edit", true);
startActivityForResult(phoneCallEditor, requestCodeTriggerPhoneCallEdit);
break;
case profileActive:
Intent profileActiveEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerProfile.class);
profileActiveEditor.putExtra(ActivityManageRule.intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
profileActiveEditor.putExtra(ActivityManageRule.intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(profileActiveEditor, requestCodeTriggerProfileEdit);
break;
case wifiConnection:
Intent wifiEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerWifi.class);
wifiEditor.putExtra("edit", true);
wifiEditor.putExtra("wifiState", selectedTrigger.getTriggerParameter());
wifiEditor.putExtra("wifiName", selectedTrigger.getTriggerParameter2());
wifiEditor.putExtra(ActivityManageTriggerWifi.intentNameWifiState, selectedTrigger.getTriggerParameter());
wifiEditor.putExtra(ActivityManageTriggerWifi.intentNameWifiName, selectedTrigger.getTriggerParameter2());
startActivityForResult(wifiEditor, requestCodeTriggerWifiEdit);
break;
case deviceOrientation:
@@ -284,8 +308,19 @@ public class ActivityManageRule extends Activity
devicePositionEditor.putExtra(ActivityManageTriggerDeviceOrientation.vectorFieldNa