Compare commits

...

116 Commits

Author SHA1 Message Date
2361c758c9 store descriptions 2022-06-06 20:06:11 +02:00
f738e02b72 store descriptions 2022-06-06 02:47:51 +02:00
f5a3636222 intent pairs for sendBroadcast 2022-06-04 14:32:20 +02:00
bb1b3b0149 tethering detection 2022-06-04 02:44:26 +02:00
b35208b7aa tethering detection 2022-06-03 19:26:34 +02:00
b3ad72cc50 wifi receiver efficiency 2022-06-02 17:55:02 +02:00
c1809bd23c run executable action 2022-06-02 17:41:41 +02:00
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
00f296d2d1 wifi action 2022-06-01 22:36:30 +02:00
e84842361c Merge remote-tracking branch 'origin/development-stable' into development 2022-05-29 22:30:16 +02:00
efaf0ed270 wifi toggle dialog reduced 2022-05-29 22:29:58 +02:00
7167f0c03d run executable 2022-05-29 20:14:50 +02:00
a9673e65b9 crash when editing notification trigger 2022-05-29 15:13:30 +02:00
592abe5b0d not contains comparator 2022-05-29 14:17:11 +02:00
dd7c3cb1d6 not contains comparator 2022-05-29 14:15:47 +02:00
38665ccd92 Merge remote-tracking branch 'origin/development-stable' into development 2022-05-29 14:04:44 +02:00
c60347b990 syntax errors in translations fixed 2022-05-29 14:04:32 +02:00
1e7ccf5200 not equals direction 2022-05-29 13:57:47 +02:00
9b84b8dad7 translations 2022-05-29 13:38:57 +02:00
a19c84ea51 send broadcasts action 2022-05-29 02:42:12 +02:00
3a14a56fd0 translations 2022-05-28 19:54:29 +02:00
2dfc538343 screenstate no sec lock screen fixed 2022-05-27 20:21:13 +02:00
67a58077cc time class changed 2022-05-26 18:47:30 +02:00
df68f7ca5c delayed lock screen 2022-05-26 18:26:49 +02:00
ad18313284 delayed lock screen 2022-05-26 15:50:39 +02:00
29a93e0e43 language updates and screen locked trigger 2022-05-24 17:40:11 +02:00
a5d54c18d8 language updates and screen locked trigger 2022-05-24 17:31:25 +02:00
62f5ad0005 operator change 2022-05-23 22:59:00 +02:00
4eb7133d9d operator change 2022-05-23 22:45:54 +02:00
343cbba8f8 broadcast trigger 2022-05-23 20:28:56 +02:00
51caae0794 operator change 2022-05-22 23:07:05 +02:00
e39a2411ba broadcast trigger 2022-05-22 17:31:55 +02:00
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
a7c4cc0965 app picker removed from play store version 2022-05-21 14:06:09 +02:00
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
7e12a0f3e5 full day time window 2022-05-21 13:34:44 +02:00
5786c1bfd4 full day time window 2022-05-21 02:33:56 +02:00
cf500c740e new release prep 2022-05-15 01:54:56 +02:00
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
7046cccabe new release prep 2022-05-15 01:37:18 +02:00
bdbed3dbef app info text updated 2022-05-10 12:42:14 +02:00
3f36c4c6b3 bug when picking app to start 2022-05-09 20:09:11 +02:00
52a10fe626 bug when importing config while service is not running 2022-05-08 20:04:45 +02:00
9fce7d987e bug when importing config while service is not running 2022-05-08 14:50:40 +02:00
d5ce04f80b wifi trigger, memorize most recent ssid 2022-05-07 02:06:17 +02:00
62c97832a9 fix in DateTimeTrigger management and executions when service already stopped 2022-04-04 20:21:34 +02:00
391edc59bf fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 20:25:10 +02:00
0d3a13e753 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 16:20:20 +02:00
152b0c3c49 fix in DateTimeTrigger management and executions when service already stopped 2022-04-03 14:46:28 +02:00
7ed04c7ae2 cosmetics 2022-03-29 17:56:04 +02:00
c688a4c460 TimeFrame repetition fix 2022-03-26 20:00:50 +01:00
5a09962cc9 TimeFrame repetition fix 2022-03-26 20:00:19 +01:00
0368b2a8c8 v118 2022-03-13 16:06:10 +01:00
965bf55811 Merge remote-tracking branch 'origin/development-stable' into development 2022-03-05 20:59:33 +01:00
217f459833 nfc fix 2022-03-05 20:59:16 +01:00
13fd4c2aae magnetometer 2022-03-05 02:00:16 +01:00
195a60cfe0 magnetometer 2022-03-03 17:32:06 +01:00
76563eb89b Merge remote-tracking branch 'origin/development-stable' into development 2022-02-28 13:46:42 +01:00
4c9e61618b profile delete bug fixed 2022-02-28 13:46:18 +01:00
e719114166 parallel rule execution 2022-02-27 18:01:54 +01:00
7733d57435 gradle 2022-02-26 13:02:07 +01:00
481e4d1896 screen state string 2022-02-23 18:09:21 +01:00
0bd64e4a53 operator change 2022-02-22 23:08:25 +01:00
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
c569ab798c Android 11 2022-02-22 22:15:27 +01:00
4e46878009 wrong field changed 2022-02-22 17:55:43 +01:00
619f348a28 Merge remote-tracking branch 'origin/development-stable' into development 2022-02-20 18:57:38 +01:00
72ccdd99f9 logging 2022-02-20 18:57:13 +01:00
c9d7399068 logging 2022-02-14 20:06:20 +01:00
9bf353ea3a logging 2022-02-12 20:04:19 +01:00
af90b566c8 new triggers: service or device starts 2022-02-07 20:09:45 +01:00
0e51c577d5 new triggers: service or device starts 2022-02-06 20:12:11 +01:00
275091f9d7 libs 2022-02-06 15:02:07 +01:00
bc31c9a4c8 translation 2022-02-05 13:47:43 +01:00
b02220609b show profile on main screen 2022-02-03 14:08:47 +01:00
da244d1bbe show profile on main screen 2022-02-03 14:05:42 +01:00
d402986dc3 ringtone 2022-02-03 13:41:05 +01:00
85eee6c4da Android 11 2022-02-02 23:35:24 +01:00
34883519e4 ringtone 2022-02-02 18:06:37 +01:00
92e405d396 Media playing trigger 2022-01-30 22:19:08 +01:00
1a8ce579a7 Media playing trigger 2022-01-30 22:08:55 +01:00
5899dd86f5 media playback listener 2022-01-30 20:13:56 +01:00
9387e8bdb2 media playback listener 2022-01-29 02:12:55 +01:00
5ed024774e Control media playback 2022-01-27 23:05:54 +01:00
e76f9f69db control media playback 2022-01-27 11:35:46 +01:00
0f1a12d28f control media playback 2022-01-27 11:34:04 +01:00
abaa961d3a Control media playback 2022-01-26 22:53:02 +01:00
5f0eab5b30 control media playback 2022-01-26 21:40:29 +01:00
92cb71ff2d Control media playback 2022-01-25 23:10:37 +01:00
71adc83b39 control media playback 2022-01-25 18:08:46 +01:00
88f4d65b19 control media playback 2022-01-24 20:13:35 +01:00
0c5b4d3874 screen state trigger 2022-01-23 18:54:17 +01:00
d64ea8454e screen state trigger 2022-01-22 02:20:34 +01:00
94f6418076 notification action 2022-01-21 21:52:27 +01:00
83ee19b4fa ScreenStateReceiver 2022-01-21 20:57:42 +01:00
5ed6097ed6 libs updated 2022-01-21 19:28:42 +01:00
7e9d03104c Merge remote-tracking branch 'origin/development-stable' into development 2022-01-21 14:31:04 +01:00
2e3e829abb Bugfix in sendTextMessage variable replacement 2022-01-21 13:56:21 +01:00
06080bb456 Update 'app/src/main/java/com/jens/automation2/Actions.java' 2022-01-21 13:00:44 +01:00
a5fd23949d screen status trigger 2022-01-20 17:57:13 +01:00
59c7a2d313 Notification channels 2022-01-17 20:09:46 +01:00
ec61a3ffa5 Service notification hint 2022-01-16 20:24:12 +01:00
a0c4cb7b6f notification action 2022-01-15 23:36:42 +01:00
22899347a1 close notification action 2022-01-15 13:47:39 +01:00
4b84a0c2f5 close notification action 2022-01-15 01:41:00 +01:00
724192e80b close notification action 2022-01-14 19:57:32 +01:00
e6a7e2c5b5 ringmode bug fixed 2022-01-14 19:31:13 +01:00
e010e3392f ringmode bug fixed 2022-01-14 19:30:06 +01:00
f0853b3a30 close notification action 2022-01-11 17:27:07 +01:00
98185a79df close notification action 2022-01-11 16:04:04 +01:00
246a02371a notification action 2022-01-10 23:00:36 +01:00
9b8ae2271b Notification action 2022-01-10 19:57:55 +01:00
b2cd3cf17c Merge remote-tracking branch 'origin/notification_action' into development 2022-01-10 19:33:24 +01:00
cf4ec286ae Notification action 2022-01-10 19:32:44 +01:00
12f44aca8b notification action 2022-01-09 22:42:47 +01:00
87edd595ba notification trigger 2022-01-09 15:22:03 +01:00
125 changed files with 7177 additions and 2241 deletions

View File

@ -8,11 +8,11 @@ android {
defaultConfig {
applicationId "com.jens.automation2"
minSdkVersion 16
compileSdkVersion 29
compileSdkVersion 31
buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy'
versionCode 117
versionName "1.7.3"
versionCode 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'
}

View File

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

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"
@ -66,6 +65,7 @@
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-feature
android:name="android.hardware.telephony"
@ -73,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"
@ -147,14 +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">

View File

@ -5,12 +5,14 @@ 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.util.ArrayList;
import java.util.Calendar;
@ -20,24 +22,23 @@ 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>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
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;
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;
private static Date lastActivatedRuleActivationTime;
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,12 +235,16 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
{
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)
{
@ -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);
}
@ -377,6 +392,7 @@ public class Rule implements Comparable<Rule>
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,24 +492,21 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
@ -530,12 +543,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -544,6 +551,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -553,13 +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>();
@ -811,29 +661,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -931,4 +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;
}
}

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.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-feature
android:name="android.hardware.telephony"
@ -71,6 +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"
@ -145,14 +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">

View File

@ -5,10 +5,12 @@ 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.jens.automation2.receivers.BroadcastListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@ -17,24 +19,23 @@ 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>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
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;
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;
private static Date lastActivatedRuleActivationTime;
protected static Date lastActivatedRuleActivationTime;
public Calendar getLastExecution()
{
@ -182,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)
@ -230,12 +232,16 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
{
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)
{
@ -309,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:
@ -338,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;
@ -348,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);
}
@ -374,6 +389,7 @@ public class Rule implements Comparable<Rule>
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;
}
@ -406,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();
@ -414,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;
}
@ -449,24 +465,21 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
@ -503,12 +516,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -517,6 +524,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -526,13 +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
}
}
}
@ -581,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>();
@ -784,29 +634,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -904,4 +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;
}
}

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"
@ -139,14 +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">

View File

@ -5,12 +5,14 @@ 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.util.ArrayList;
import java.util.Calendar;
@ -20,24 +22,23 @@ 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>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
protected static List<Rule> ruleRunHistory = new ArrayList<Rule>();
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;
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;
private static Date lastActivatedRuleActivationTime;
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,12 +235,16 @@ public class Rule implements Comparable<Rule>
}
if(!changeExistingRule)
{
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)
{
@ -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);
}
@ -377,6 +392,7 @@ public class Rule implements Comparable<Rule>
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,24 +492,21 @@ public class Rule implements Comparable<Rule>
* Will activate the rule. Should be called by a separate execution thread
* @param automationService
*/
protected boolean activateInternally(AutomationService automationService, boolean force)
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggable = isActuallyToggable();
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggable;
boolean doToggle = ruleToggle && isActuallyToggleable;
//if(notLastActive || force || doToggle)
// if(force || doToggle)
// {
String message;
if(!doToggle)
message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName());
else
message = String.format(automationService.getResources().getString(R.string.ruleActivateToggle), Rule.this.getName());
Miscellaneous.logEvent("i", "Rule", message, 2);
// automationService.speak(message);
// Toast.makeText(automationService, message, Toast.LENGTH_LONG).show();
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
@ -530,12 +543,6 @@ public class Rule implements Comparable<Rule>
}
Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2);
// }
// else
// {
// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3);
// return false;
// }
return true;
}
@ -544,6 +551,9 @@ public class Rule implements Comparable<Rule>
public void activate(AutomationService automationService, boolean force)
{
ActivateRuleTask task = new ActivateRuleTask();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
else
task.execute(automationService, force);
}
@ -553,13 +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>();
@ -811,29 +661,6 @@ public class Rule implements Comparable<Rule>
return ruleCandidates;
}
/*public static ArrayList<Rule> findRuleCandidatesByHeadphoneJack(boolean triggerParameter)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
for(Rule oneRule : ruleCollection)
{
innerloop:
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.headsetPlugged)
{
if(oneTrigger.getTriggerParameter() == triggerParameter)
{
ruleCandidates.add(oneRule);
break innerloop; //we don't need to search the other triggers in the same rule
}
}
}
}
return ruleCandidates;
}*/
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
{
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
@ -931,4 +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;
}
}

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

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,10 +20,11 @@ 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 {
public enum Action_Enum
{
setWifi,
setBluetooth,
setUsbTethering,
@ -41,9 +45,14 @@ public class Action
setDataConnection,
speakText,
playMusic,
controlMediaPlayback,
setScreenBrightness,
playSound,
vibrate,
createNotification,
closeNotification,
sendBroadcast,
runExecutable,
sendTextMessage;
public String getFullName(Context context)
@ -102,12 +111,22 @@ public class Action
return context.getResources().getString(R.string.actionSpeakText);
case playMusic:
return context.getResources().getString(R.string.actionPlayMusic);
case controlMediaPlayback:
return context.getResources().getString(R.string.actionMediaControl);
case playSound:
return context.getResources().getString(R.string.playSound);
case sendTextMessage:
return context.getResources().getString(R.string.sendTextMessage);
case setScreenBrightness:
return context.getResources().getString(R.string.setScreenBrightness);
case createNotification:
return context.getResources().getString(R.string.createNotification);
case closeNotification:
return context.getResources().getString(R.string.closeNotifications);
case sendBroadcast:
return context.getResources().getString(R.string.sendBroadcast);
case runExecutable:
return context.getResources().getString(R.string.runExecutable);
default:
return "Unknown";
}
@ -154,6 +173,8 @@ public class Action
{
StringBuilder returnString = new StringBuilder();
try
{
switch (getAction())
{
case setWifi:
@ -216,6 +237,9 @@ public class Action
case playMusic:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionPlayMusic));
break;
case controlMediaPlayback:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.actionMediaControl));
break;
case sendTextMessage:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendTextMessage));
break;
@ -237,6 +261,18 @@ public class Action
case setScreenBrightness:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.setScreenBrightness));
break;
case createNotification:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.createNotification));
break;
case closeNotification:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.closeNotifications));
break;
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());
}
@ -256,7 +292,7 @@ public class Action
}
else if (this.getAction().equals(Action_Enum.startOtherActivity))
{
returnString.append(": " + parameter2.replace(Action.intentPairSeperator, "/"));
returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/"));
}
else if (this.getAction().equals(Action_Enum.sendTextMessage))
{
@ -279,9 +315,66 @@ public class Action
returnString.append(" / " + Integer.parseInt(parameter2) + "%");
}
else if (this.getAction().equals(Action_Enum.closeNotification))
{
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.from) + " ");
String parts[] = this.getParameter2().split(Action.actionParameter2Split);
if (parts[0].equals(Trigger.anyAppString))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.anyApp));
else
if (parameter2 != null && parameter2.length() > 0)
returnString.append(": " + parameter2);
returnString.append(parts[0]);
if (!StringUtils.isBlank(parts[2]))
returnString.append(", " + Miscellaneous.getAnyContext().getResources().getString(R.string.ifString) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.title) + " " + Trigger.getMatchString(parts[1]) + " " + parts[2]);
if (parts.length > 4 && !StringUtils.isBlank(parts[4]))
returnString.append(", " + Miscellaneous.getAnyContext().getResources().getString(R.string.ifString) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.text) + " " + Trigger.getMatchString(parts[3]) + " " + parts[4]);
}
else if(this.getAction().equals(Action_Enum.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, "; "));
}
catch (Exception e)
{
returnString.append(": " + Miscellaneous.getAnyContext().getResources().getString(R.string.error));
}
return returnString.toString();
}
@ -439,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;
@ -451,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;

View File

@ -8,13 +8,15 @@ import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
@ -24,11 +26,13 @@ import android.os.PowerManager.WakeLock;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telephony.SmsManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.WindowManager;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
@ -37,7 +41,9 @@ import com.jens.automation2.actions.wifi_router.MyOnStartTetheringCallback;
import com.jens.automation2.actions.wifi_router.MyOreoWifiManager;
import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.NotificationListener;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
@ -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,6 +93,123 @@ public class Actions
public static final String wireguard_tunnel_down = "com.wireguard.android.action.SET_TUNNEL_DOWN";
public static final String wireguard_tunnel_refresh = "com.wireguard.android.action.REFRESH_TUNNEL_STATES";
public static void createNotification(Action action)
{
String[] elements = action.getParameter2().split(Action.actionParameter2Split);
Miscellaneous.logEvent("w", "createNotification", "Creating notification with title " + elements[0] + " and text " + elements[1], 3);
int notificationId = Math.round(Calendar.getInstance().getTimeInMillis()/1000);
try
{
String title = Miscellaneous.replaceVariablesInText(elements[0], Miscellaneous.getAnyContext());
String text = Miscellaneous.replaceVariablesInText(elements[1], Miscellaneous.getAnyContext());
Miscellaneous.createDismissibleNotification(title, text, notificationId, false, AutomationService.NOTIFICATION_CHANNEL_ID_RULES, null);
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "createNotification", "Error occurred while replacing vars: " + Log.getStackTraceString(e), 3);
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static void closeNotification(Action action)
{
NotificationManager nm = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
for(StatusBarNotification n : nm.getActiveNotifications())
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
String[] params = action.getParameter2().split(Action.actionParameter2Split);
String myApp = params[0];
String myTitleDir = params[1];
String requiredTitle = params[2];
String myTextDir = params[3];
String requiredText;
if (params.length >= 5)
requiredText = params[4];
else
requiredText = "";
for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications())
{
NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn);
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Checking if this notification should be closed in the context of rule " + action.getParentRule().getName() + ": "+ sn.toString(), 5);
if (!myApp.equals(Trigger.anyAppString))
{
if (!myApp.equalsIgnoreCase(sn.getApp()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification app name does not match rule.", 5);
continue;
}
}
else
{
/*
Notifications from Automation are disregarded to avoid infinite loops.
*/
if(myApp.equals(BuildConfig.APPLICATION_ID))
{
continue;
}
}
/*
If there are multiple notifications ("stacked") title or text might be null:
https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications
*/
// T I T L E
if (!StringUtils.isEmpty(requiredTitle))
{
if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification title does not match rule.", 5);
continue;
}
}
// T E X T
if (!StringUtils.isEmpty(requiredText))
{
if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText()))
{
Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification text does not match rule.", 5);
continue;
}
}
Miscellaneous.logEvent("i", "NotificationCloseCheck", "All criteria matches. Closing notification: " + sbn.getNotification().toString(), 3);
if(NotificationListener.getInstance() != null)
NotificationListener.getInstance().dismissNotification(sbn);
else
Miscellaneous.logEvent("i", "NotificationCloseCheck", "NotificationListener instance is null. Can\'t close notification.", 3);
}
}
}
}
public static 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);
@ -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;
}
}

View File

@ -10,6 +10,7 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
@ -20,8 +21,9 @@ import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
public class ActivityMaintenance extends Activity
public class ActivityControlCenter extends Activity
{
final static int requestCodeImport = 1001;
final static int requestCodeExport = 1002;
@ -30,13 +32,14 @@ public class ActivityMaintenance extends Activity
final static String prefsFileName = "com.jens.automation2_preferences.xml";
TextView tvFileStoreLocation, tvAppVersion;
Button bVolumeTest, bMoreSettings, bSettingsSetToDefault, bShareConfigAndLog, bImportConfiguration, bExportConfiguration;
Button bVolumeTest, bMoreSettings, bSettingsSetToDefault, bSendEmailToDev, bImportConfiguration, bExportConfiguration;
CheckBox chkShareConfigAndLog;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintenance);
setContentView(R.layout.activity_control_center);
bVolumeTest = (Button) findViewById(R.id.bVolumeTest);
bVolumeTest.setOnClickListener(new View.OnClickListener()
@ -44,18 +47,25 @@ public class ActivityMaintenance extends Activity
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMaintenance.this, ActivityVolumeTest.class);
Intent intent = new Intent(ActivityControlCenter.this, ActivityVolumeTest.class);
startActivity(intent);
}
});
bShareConfigAndLog = (Button) findViewById(R.id.bShareConfigAndLog);
bShareConfigAndLog.setOnClickListener(new View.OnClickListener()
chkShareConfigAndLog = (CheckBox)findViewById(R.id.chkShareConfigAndLog);
bSendEmailToDev = (Button) findViewById(R.id.bSendEmailToDev);
bSendEmailToDev.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
getShareConfigAndLogDialogue(ActivityMaintenance.this).show();
if(chkShareConfigAndLog.isChecked())
getShareConfigAndLogDialogue(ActivityControlCenter.this).show();
else
{
String subject = "Automation";
Miscellaneous.sendEmail(ActivityControlCenter.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), null);
}
}
});
@ -65,17 +75,17 @@ public class ActivityMaintenance extends Activity
@Override
public void onClick(View v)
{
getDefaultSettingsDialog(ActivityMaintenance.this).show();
getDefaultSettingsDialog(ActivityControlCenter.this).show();
}
});
Button bMoreSettings = (Button) findViewById(R.id.bMoreSettings);
bMoreSettings = (Button) findViewById(R.id.bMoreSettings);
bMoreSettings.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(ActivityMaintenance.this, ActivitySettings.class);
Intent myIntent = new Intent(ActivityControlCenter.this, ActivitySettings.class);
startActivityForResult(myIntent, requestCodeMoreSettings);
}
});
@ -123,7 +133,7 @@ public class ActivityMaintenance extends Activity
if (AutomationService.isMyServiceRunning(this))
AutomationService.getInstance().serviceInterface(AutomationService.serviceCommands.reloadSettings);
if (AutomationService.isMyServiceRunning(ActivityMaintenance.this))
if (AutomationService.isMyServiceRunning(ActivityControlCenter.this))
Toast.makeText(this, getResources().getString(R.string.settingsWillTakeTime), Toast.LENGTH_LONG).show();
break;
@ -170,7 +180,7 @@ public class ActivityMaintenance extends Activity
if (Miscellaneous.copyDocumentFileToFile(file, dstRules))
filesImported++;
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.rulesImportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.rulesImportError), Toast.LENGTH_LONG).show();
}
}
else if (file.getName().equals(prefsFileName))
@ -183,7 +193,7 @@ public class ActivityMaintenance extends Activity
if (Miscellaneous.copyDocumentFileToFile(file, dstPrefs))
filesImported++;
else
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.prefsImportError), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.prefsImportError), Toast.LENGTH_LONG).show();
}
}
}
@ -191,12 +201,12 @@ public class ActivityMaintenance extends Activity
if(applicableFilesFound > 0)
{
if(filesImported == 0)
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.noFilesImported), Toast.LENGTH_LONG).show();
else if(filesImported < applicableFilesFound)
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.notAllFilesImported), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.notAllFilesImported), Toast.LENGTH_LONG).show();
else if (filesImported == applicableFilesFound)
{
Toast.makeText(ActivityMaintenance.this, getResources().getString(R.string.configurationImportedSuccessfully), Toast.LENGTH_LONG).show();
Toast.makeText(ActivityControlCenter.this, getResources().getString(R.string.configurationImportedSuccessfully), Toast.LENGTH_LONG).show();
try
{
@ -208,19 +218,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)
@ -319,9 +333,10 @@ public class ActivityMaintenance extends Activity
Uri uri = Uri.parse("content://com.jens.automation2/" + Settings.zipFileName);
Miscellaneous.sendEmail(ActivityMaintenance.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), uri);
Miscellaneous.sendEmail(ActivityControlCenter.this, "android-development@gmx.de", "Automation logs", getSystemInfo(), uri);
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
@ -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();
}
}

View File

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

View File

@ -3,7 +3,6 @@ package com.jens.automation2;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -11,7 +10,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@ -29,29 +27,25 @@ import androidx.core.text.HtmlCompat;
import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.CellLocationChangedReceiver;
import com.jens.automation2.location.LocationProvider;
import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Calendar;
@SuppressLint("NewApi")
public class ActivityMainScreen extends ActivityGeneric
{
private static boolean guiChangeInProgress = false;
static boolean guiChangeInProgress = false;
static ActivityMainScreen activityMainScreenInstance = null;
static boolean updateNoteDisplayed = false;
static boolean uiUpdateRunning = false;
private static ActivityMainScreen activityMainScreenInstance = null;
private ToggleButton toggleService, tbLockSound;
private Button bShowHelp, bPrivacy, bSettingsErase, bAddSoundLockTIme, bDonate;
private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvlockSoundDuration;
private static boolean updateNoteDisplayed = false;
ToggleButton toggleService, tbLockSound;
Button bShowHelp, bPrivacy, bAddSoundLockTIme, bDonate, bControlCenter;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration;
private ListView lvRuleHistory;
private ArrayAdapter<Rule> ruleHistoryListViewAdapter;
private static boolean uiUpdateRunning = false;
ListView lvRuleHistory;
ArrayAdapter<Rule> ruleHistoryListViewAdapter;
@Override
public void onCreate(Bundle savedInstanceState)
@ -74,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;

View File

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

View File

@ -0,0 +1,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();
}
}
}

View File

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

View File

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

View File

@ -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);
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@ -12,6 +13,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.view.MotionEvent;
@ -30,6 +32,8 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import java.util.ArrayList;
@ -55,6 +59,204 @@ public class ActivityManageActionStartActivity extends Activity
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>
{
@Override
@ -76,7 +278,6 @@ public class ActivityManageActionStartActivity extends Activity
return name1.compareTo(name2);
}
}
private static List<PackageInfo> pInfos = null;
@ -331,192 +532,12 @@ public class ActivityManageActionStartActivity extends Activity
return alertDialog;
}
@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)
void getAppList()
{
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();
}
}
private void loadValuesIntoGui()
{
@ -661,4 +682,22 @@ public class ActivityManageActionStartActivity extends Activity
getActionStartActivityDialog1Application().show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == requestCodeForRequestQueryAllPackagesPermission)
{
for(int i = 0; i < permissions.length; i++)
{
if(permissions[i].equals(Manifest.permission.QUERY_ALL_PACKAGES) && grantResults[i] == PackageManager.PERMISSION_GRANTED)
{
getAppList();
break;
}
}
}
}
}

View File

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

View File

@ -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();
}
});
}
}

View File

@ -12,6 +12,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
@ -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;
@ -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 critGps = new Criteria();
critGps.setAltitudeRequired(false);
critGps.setSpeedRequired(false);
critGps.setBearingRequired(false);
critGps.setCostAllowed(true);
critGps.setAccuracy(Criteria.ACCURACY_FINE);
Criteria criteriaGps = new Criteria();
criteriaGps.setAltitudeRequired(false);
criteriaGps.setSpeedRequired(false);
criteriaGps.setBearingRequired(false);
criteriaGps.setCostAllowed(true);
criteriaGps.setAccuracy(Criteria.ACCURACY_FINE);
String provider1 = myLocationManager.getBestProvider(critNetwork, true);
String provider2 = myLocationManager.getBestProvider(critGps, true);
String provider1 = myLocationManager.getBestProvider(criteriaNetwork, true);
String provider2 = myLocationManager.getBestProvider(criteriaGps, true);
// String provider3 = myLocationManager.getProvider("wifi");
if(provider1 == null | provider2 == null)
if(provider1 == null || provider2 == null)
{
Toast.makeText(this, getResources().getString(R.string.logNoSuitableProvider), Toast.LENGTH_LONG).show();
return;
}
else
{
if(provider1.equals(provider2))
Miscellaneous.logEvent("i", "POI Manager", "Both location providers are equal. Only one will be used.", 4);
locationSearchStart = Calendar.getInstance();
startTimeout();
if(!Settings.privacyLocationing || !ConnectivityReceiver.isDataConnectionAvailable(AutomationService.getInstance()))
if(!Settings.privacyLocationing && !ConnectivityReceiver.isDataConnectionAvailable(Miscellaneous.getAnyContext()) && !provider1.equals(provider2))
{
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider1, 3);
myLocationManager.requestLocationUpdates(provider1, 500, Settings.satisfactoryAccuracyNetwork, myLocationListenerNetwork);
}
else
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location query because private locationing is active.", 4);
Miscellaneous.logEvent("i", "POI Manager", "Skipping network location.", 4);
Miscellaneous.logEvent("i", "POI Manager", getResources().getString(R.string.logGettingPositionWithProvider) + " " + provider2, 3);
myLocationManager.requestLocationUpdates(provider2, 500, Settings.satisfactoryAccuracyGps, myLocationListenerGps);
@ -310,6 +313,20 @@ public class ActivityManagePoi extends Activity
public void onClick(DialogInterface dialog, int which)
{
progressDialog = ProgressDialog.show(ActivityManagePoi.this, "", getResources().getString(R.string.gettingPosition), true, true);
if(Build.VERSION.SDK_INT >= 31)
{
AlertDialog dia = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.locationNotWorkingOn12), ActivityManagePoi.this);
dia.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
getLocation();
}
});
dia.show();
}
else
getLocation();
}
};

View File

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

View File

@ -65,21 +65,19 @@ public class ActivityManageRule extends Activity
static ProgressDialog progressDialog = null;
static Trigger_Enum triggerType;
static boolean triggerParameter;
static PointOfInterest triggerPoi;
static String triggerProcess;
static int triggerBattery;
static double triggerSpeed;
static double triggerNoise;
static TimeFrame triggerTimeFrame;
static String triggerWifiName;
static Rule ruleToEdit;
static boolean newRule;
static Trigger newTrigger;
static Action newAction;
Rule ruleToEdit = null;
ArrayAdapter<Trigger> triggerListViewAdapter;
ArrayAdapter<Action> actionListViewAdapter;
@ -102,7 +100,7 @@ public class ActivityManageRule extends Activity
final static int requestCodeTriggerDeviceOrientationAdd = 301;
final static int requestCodeTriggerDeviceOrientationEdit = 302;
final static int requestCodeTriggerNotificationAdd = 8000;
final static int requestCodeTriggerNfcNotificationEdit = 8001;
final static int requestCodeTriggerNotificationEdit = 8001;
final static int requestCodeActionPlaySoundAdd = 501;
final static int requestCodeActionPlaySoundEdit = 502;
final static int requestCodeTriggerPhoneCallAdd = 601;
@ -115,6 +113,22 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionSendTextMessageEdit = 5002;
final static int requestCodeActionVibrateAdd = 801;
final static int requestCodeActionVibrateEdit = 802;
final static int requestCodeActionCreateNotificationAdd = 803;
final static int requestCodeActionCreateNotificationEdit = 804;
final static int requestCodeActionCloseNotificationAdd = 805;
final static int requestCodeActionCloseNotificationEdit = 806;
final static int requestCodeActionControlMediaAdd = 807;
final static int requestCodeActionControlMediaEdit = 808;
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()
{
@ -127,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);
@ -144,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);
@ -155,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()
{
@ -253,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:
@ -266,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;
@ -293,6 +308,17 @@ public class ActivityManageRule extends Activity
devicePositionEditor.putExtra(ActivityManageTriggerDeviceOrientation.vectorFieldName, selectedTrigger.getTriggerParameter2());
startActivityForResult(devicePositionEditor, requestCodeTriggerDeviceOrientationEdit);
break;
case broadcastReceived:
Intent broadcastEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerBroadcast.class);
broadcastEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
broadcastEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(broadcastEditor, requestCodeTriggerBroadcastReceivedEdit);
break;
case tethering:
Intent tetheringEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTethering.class);
tetheringEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
startActivityForResult(tetheringEditor, requestCodeTriggerTetheringEdit);
break;
default:
break;
}
@ -353,8 +379,8 @@ public class ActivityManageRule extends Activity
break;
case setScreenBrightness:
Intent activityEditScreenBrightnessIntent = new Intent(ActivityManageRule.this, ActivityManageActionBrightnessSetting.class);
activityEditScreenBrightnessIntent.putExtra("autoBrightness", a.getParameter1());
activityEditScreenBrightnessIntent.putExtra("brightnessValue", Integer.parseInt(a.getParameter2()));
activityEditScreenBrightnessIntent.putExtra(ActivityManageActionBrightnessSetting.intentNameAutoBrightness, a.getParameter1());
activityEditScreenBrightnessIntent.putExtra(ActivityManageActionBrightnessSetting.intentNameBrightnessValue, Integer.parseInt(a.getParameter2()));
startActivityForResult(activityEditScreenBrightnessIntent, requestCodeActionScreenBrightnessEdit);
break;
case vibrate:
@ -362,6 +388,40 @@ public class ActivityManageRule extends Activity
activityEditVibrateIntent.putExtra("vibratePattern", a.getParameter2());
startActivityForResult(activityEditVibrateIntent, requestCodeActionVibrateEdit);
break;
case sendBroadcast:
Intent activityEditSendBroadcastIntent = new Intent(ActivityManageRule.this, ActivityManageActionSendBroadcast.class);
activityEditSendBroadcastIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditSendBroadcastIntent, requestCodeActionSendBroadcastEdit);
break;
case runExecutable:
Intent activityEditRunExecutableIntent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class);
activityEditRunExecutableIntent.putExtra(intentNameActionParameter1, a.getParameter1());
activityEditRunExecutableIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditRunExecutableIntent, requestCodeActionRunExecutableEdit);
break;
case setWifi:
Intent activityEditSetWifiIntent = new Intent(ActivityManageRule.this, ActivityManageActionWifi.class);
activityEditSetWifiIntent.putExtra(intentNameActionParameter1, a.getParameter1());
activityEditSetWifiIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditSetWifiIntent, requestCodeActionSetWifiEdit);
break;
case controlMediaPlayback:
Intent activityEditControlMediaIntent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class);
activityEditControlMediaIntent.putExtra(ActivityManageRule.intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditControlMediaIntent, requestCodeActionControlMediaEdit);
break;
case createNotification:
Intent activityEditCreateNotificationIntent = new Intent(ActivityManageRule.this, ActivityManageActionCreateNotification.class);
String[] elements = a.getParameter2().split(Action.actionParameter2Split);
activityEditCreateNotificationIntent.putExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle, elements[0]);
activityEditCreateNotificationIntent.putExtra(ActivityManageActionCreateNotification.intentNameNotificationText, elements[1]);
startActivityForResult(activityEditCreateNotificationIntent, requestCodeActionCreateNotificationEdit);
break;
case closeNotification:
Intent activityEditCloseNotificationIntent = new Intent(ActivityManageRule.this, ActivityManageActionCloseNotification.class);
activityEditCloseNotificationIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditCloseNotificationIntent, requestCodeActionCloseNotificationEdit);
break;
case playSound:
Intent actionPlaySoundIntent = new Intent(context, ActivityManageActionPlaySound.class);
actionPlaySoundIntent.putExtra("edit", true);
@ -464,7 +524,6 @@ public class ActivityManageRule extends Activity
for(int i=0; i<types.length; i++)
{
//pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped;
if(types[i].toString().equals(Trigger_Enum.pointOfInterest.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.compass_small));
else if(types[i].toString().equals(Trigger_Enum.timeFrame.toString()))
@ -487,9 +546,10 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.plane));
else if(types[i].toString().equals(Trigger_Enum.roaming.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.roaming));
else if(types[i].toString().equals(Trigger_Enum.broadcastReceived.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString()))
{
// if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageSpecificRule.this, "android.permission.SEND_SMS") && !Miscellaneous.isGooglePlayInstalled(ActivityManageSpecificRule.this))
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, "android.permission.SEND_SMS"))
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
}
@ -507,6 +567,16 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.smartphone));
else if(types[i].toString().equals(Trigger_Enum.profileActive.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Trigger_Enum.musicPlaying.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Trigger_Enum.screenState.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.smartphone));
else if(types[i].toString().equals(Trigger_Enum.deviceStarts.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.alarm));
else if(types[i].toString().equals(Trigger_Enum.serviceStarts.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.alarm));
else if(types[i].toString().equals(Trigger_Enum.tethering.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.router));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@ -567,11 +637,11 @@ public class ActivityManageRule extends Activity
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeAdd);
return;
}
else if(triggerType == Trigger_Enum.charging)
else if(triggerType == Trigger_Enum.charging || triggerType == Trigger_Enum.musicPlaying)
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
else if(triggerType == Trigger_Enum.usb_host_connection)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
else if(triggerType == Trigger_Enum.speed | triggerType == Trigger_Enum.noiseLevel | triggerType == Trigger_Enum.batteryLevel)
else if(triggerType == Trigger_Enum.speed || triggerType == Trigger_Enum.noiseLevel || triggerType == Trigger_Enum.batteryLevel)
booleanChoices = new String[]{getResources().getString(R.string.exceeds), getResources().getString(R.string.dropsBelow)};
else if(triggerType == Trigger_Enum.wifiConnection)
{
@ -588,7 +658,9 @@ public class ActivityManageRule extends Activity
return;
}
else if(triggerType == Trigger_Enum.process_started_stopped)
{
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
}
else if(triggerType == Trigger_Enum.notification)
{
newTrigger.setTriggerType(Trigger_Enum.notification);
@ -668,6 +740,27 @@ public class ActivityManageRule extends Activity
startActivityForResult(bluetoothEditor, requestCodeTriggerBluetoothAdd);
return;
}
else if(triggerType == Trigger_Enum.screenState)
{
newTrigger.setTriggerType(Trigger_Enum.screenState);
getTriggerScreenStateDialog().show();
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.lockedCommentScreenMustBeOff), ActivityManageRule.this).show();
return;
}
else if(triggerType == Trigger_Enum.deviceStarts)
{
newTrigger.setTriggerType(Trigger_Enum.deviceStarts);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
return;
}
else if(triggerType == Trigger_Enum.serviceStarts)
{
newTrigger.setTriggerType(Trigger_Enum.serviceStarts);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
return;
}
else if(triggerType == Trigger_Enum.headsetPlugged)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
@ -676,8 +769,25 @@ public class ActivityManageRule extends Activity
if (NfcReceiver.checkNfcRequirements(ActivityManageRule.this, true))
getTriggerParameterDialog(context, booleanChoices).show();
}
else if(triggerType == Trigger_Enum.broadcastReceived)
{
newTrigger.setTriggerType(Trigger_Enum.broadcastReceived);
Intent broadcastTriggerEditor = new Intent(myContext, ActivityManageTriggerBroadcast.class);
startActivityForResult(broadcastTriggerEditor, requestCodeTriggerBroadcastReceivedAdd);
return;
}
else if(triggerType == Trigger_Enum.tethering)
{
newTrigger.setTriggerType(Trigger_Enum.tethering);
Intent tetheringTriggerEditor = new Intent(myContext, ActivityManageTriggerTethering.class);
startActivityForResult(tetheringTriggerEditor, requestCodeTriggerTetheringAdd);
return;
}
else
getTriggerParameterDialog(context, booleanChoices).show();
if(triggerType.equals(Trigger_Enum.process_started_stopped))
Miscellaneous.messageBox(getResources().getString(R.string.info), String.format(getResources().getString(R.string.featureCeasedToWorkLastWorkingAndroidVersion), "7"), ActivityManageRule.this).show();
}
});
@ -687,7 +797,7 @@ public class ActivityManageRule extends Activity
private AlertDialog getTriggerParameterDialog(final Context myContext, final String[] choices)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(getResources().getString(R.string.selectTypeOfTrigger));
alertDialogBuilder.setTitle(getResources().getString(R.string.selectParameters));
alertDialogBuilder.setItems(choices, new DialogInterface.OnClickListener()
{
@Override
@ -999,6 +1109,36 @@ public class ActivityManageRule extends Activity
return alertDialog;
}
private AlertDialog getTriggerScreenStateDialog()
{
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle(Miscellaneous.getAnyContext().getResources().getString(R.string.selectDesiredState));
String[] choices = {
Miscellaneous.getAnyContext().getResources().getString(R.string.off),
Miscellaneous.getAnyContext().getResources().getString(R.string.on),
Miscellaneous.getAnyContext().getResources().getString(R.string.unlocked),
Miscellaneous.getAnyContext().getResources().getString(R.string.lockedWithoutSecurity),
Miscellaneous.getAnyContext().getResources().getString(R.string.lockedWithSecurity)
};
alertDialog.setItems(choices, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
newTrigger.setTriggerParameter(true);
newTrigger.setTriggerParameter2(String.valueOf(which));
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
}
});
return alertDialog.create();
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private AlertDialog getTriggerActivityDetectionDialog()
{
@ -1088,9 +1228,6 @@ public class ActivityManageRule extends Activity
});
AlertDialog alertDialog = alertDialogBuilder.create();
// Log.i("Amount of Applications", String.valueOf(applicationArray.length));
// Log.i("Amount of Packages", String.valueOf(ActivityManageStartActivity.getPackageListString(myContext).length));
return alertDialog;
}
@ -1127,6 +1264,7 @@ public class ActivityManageRule extends Activity
triggerProcess = activityArray[which];
newTrigger.setTriggerType(Trigger_Enum.process_started_stopped);
newTrigger.setProcessName(triggerProcess);
newTrigger.setTriggerParameter2(packageName + Trigger.triggerParameter2Split + triggerProcess);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
}
@ -1174,9 +1312,15 @@ public class ActivityManageRule extends Activity
else if(requestCode == requestCodeTriggerTimeframeEdit)
{
//edit TimeFrame
if(resultCode == RESULT_OK && ActivityManageTriggerTimeFrame.editedTimeFrameTrigger != null)
if(resultCode == RESULT_OK && data.hasExtra(intentNameTriggerParameter2))
{
ActivityManageTriggerTimeFrame.editedTimeFrameTrigger.setParentRule(ruleToEdit);
Trigger responseTimeFrame = new Trigger();
responseTimeFrame.setTriggerType(Trigger_Enum.timeFrame);
responseTimeFrame.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
responseTimeFrame.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
responseTimeFrame.setTimeFrame(new TimeFrame(data.getStringExtra(intentNameTriggerParameter2)));
responseTimeFrame.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, responseTimeFrame);
this.refreshTriggerList();
}
else
@ -1260,12 +1404,22 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerNfcNotificationEdit)
else if(requestCode == requestCodeTriggerNotificationEdit)
{
if(resultCode == RESULT_OK)
{
newTrigger = ActivityManageTriggerNotification.resultingTrigger;
newTrigger.setParentRule(ruleToEdit);
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.notification);
editedTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageTriggerNotification.intentNameNotificationDirection, false));
editedTrigger.setTriggerParameter2(
data.getStringExtra(ActivityManageTriggerNotification.intentNameNotificationApp) + Trigger.triggerParameter2Split +
data.getStringExtra(ActivityManageTriggerNotification.intentNameNotificationTitleDir) + Trigger.triggerParameter2Split +
data.getStringExtra(ActivityManageTriggerNotification.intentNameNotificationTitle) + Trigger.triggerParameter2Split +
data.getStringExtra(ActivityManageTriggerNotification.intentNameNotificationTextDir) + Trigger.triggerParameter2Split +
data.getStringExtra(ActivityManageTriggerNotification.intentNameNotificationText)
);
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
@ -1275,7 +1429,7 @@ public class ActivityManageRule extends Activity
{
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
newTrigger.setTriggerParameter2(data.getStringExtra("triggerParameter2"));
newTrigger.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
this.refreshTriggerList();
}
}
@ -1335,8 +1489,8 @@ public class ActivityManageRule extends Activity
{
if(resultCode == RESULT_OK)
{
newAction.setParameter1(data.getBooleanExtra("autoBrightness", false));
newAction.setParameter2(String.valueOf(data.getIntExtra("brightnessValue", 0)));
newAction.setParameter1(data.getBooleanExtra(ActivityManageActionBrightnessSetting.intentNameAutoBrightness, false));
newAction.setParameter2(String.valueOf(data.getIntExtra(ActivityManageActionBrightnessSetting.intentNameBrightnessValue, 0)));
newAction.setParentRule(ruleToEdit);
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
@ -1367,6 +1521,72 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionSendBroadcastAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionRunExecutableAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, false));
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionControlMediaAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(data.getStringExtra(ActivityManageRule.intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionSetWifiAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter1(data.getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true));
newAction.setParameter2(data.getStringExtra(ActivityManageRule.intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCreateNotificationAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle)
+ Action.actionParameter2Split +
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationText)
);
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCloseNotificationAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionVibrateEdit)
{
if(resultCode == RESULT_OK)
@ -1379,6 +1599,88 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionSendBroadcastEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionRunExecutableEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter1) && data.hasExtra(intentNameActionParameter2))
{
ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, false));
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
}
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionSetWifiEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter1) && data.hasExtra(intentNameActionParameter2))
{
ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, false));
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
}
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionControlMediaEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCreateNotificationEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle))
ruleToEdit.getActionSet().get(editIndex).setParameter2(
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationTitle)
+ Action.actionParameter2Split +
data.getStringExtra(ActivityManageActionCreateNotification.intentNameNotificationText)
);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionCloseNotificationEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionPlaySoundAdd)
{
if(resultCode == RESULT_OK)
@ -1472,6 +1774,52 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerBroadcastReceivedAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerBroadcastReceivedEdit)
{
if(resultCode == RESULT_OK)
{
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.broadcastReceived);
editedTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
editedTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerTetheringAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerTetheringEdit)
{
if(resultCode == RESULT_OK)
{
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.tethering);
editedTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
}
protected AlertDialog getActionTypeDialog()
@ -1513,12 +1861,22 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.talking));
else if(types[i].toString().equals(Action_Enum.playMusic.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.tune));
else if(types[i].toString().equals(Action_Enum.controlMediaPlayback.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.tune));
else if(types[i].toString().equals(Action_Enum.setScreenBrightness.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.brightness));
else if(types[i].toString().equals(Action_Enum.playSound.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else if(types[i].toString().equals(Action_Enum.vibrate.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.vibrate));
else if(types[i].toString().equals(Action_Enum.createNotification.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Action_Enum.closeNotification.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Action_Enum.sendBroadcast.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
else if(types[i].toString().equals(Action_Enum.runExecutable.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.script));
else if(types[i].toString().equals(Action_Enum.sendTextMessage.toString()))
{
// if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageSpecificRule.this, "android.permission.SEND_SMS") && !Miscellaneous.isGooglePlayInstalled(ActivityManageSpecificRule.this))
@ -1568,10 +1926,8 @@ public class ActivityManageRule extends Activity
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setWifi.toString()))
{
newAction.setAction(Action_Enum.setWifi);
getActionParameter1Dialog(ActivityManageRule.this).show();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
Miscellaneous.messageBox(context.getResources().getString(R.string.app_name), context.getResources().getString(R.string.android10WifiToggleNotice), context).show();
Intent editSetWifiIntent = new Intent(context, ActivityManageActionWifi.class);
startActivityForResult(editSetWifiIntent, requestCodeActionSetWifiAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setBluetooth.toString()))
{
@ -1681,6 +2037,36 @@ public class ActivityManageRule extends Activity
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionVibrate.class);
startActivityForResult(intent, requestCodeActionVibrateAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.sendBroadcast.toString()))
{
newAction.setAction(Action_Enum.sendBroadcast);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionSendBroadcast.class);
startActivityForResult(intent, requestCodeActionSendBroadcastAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.runExecutable.toString()))
{
newAction.setAction(Action_Enum.runExecutable);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class);
startActivityForResult(intent, requestCodeActionRunExecutableAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString()))
{
newAction.setAction(Action_Enum.controlMediaPlayback);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class);
startActivityForResult(intent, requestCodeActionControlMediaAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.createNotification.toString()))
{
newAction.setAction(Action_Enum.createNotification);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCreateNotification.class);
startActivityForResult(intent, requestCodeActionCreateNotificationAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.closeNotification.toString()))
{
newAction.setAction(Action_Enum.closeNotification);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCloseNotification.class);
startActivityForResult(intent, requestCodeActionCloseNotificationAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setScreenBrightness.toString()))
{
newAction.setAction(Action_Enum.setScreenBrightness);

View File

@ -0,0 +1,421 @@
package com.jens.automation2;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
public class ActivityManageTriggerBroadcast extends Activity
{
RadioButton rbBroadcastReceived, rbBroadcastNotReceived;
EditText etBroadcastTriggerAction;
Button bBroadcastShowSuggestions, bSaveTriggerBroadcast;
TextView tvBroadcastUrl;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_trigger_broadcasts);
bBroadcastShowSuggestions = findViewById(R.id.bBroadcastShowSuggestions);
bSaveTriggerBroadcast = findViewById(R.id.bSaveTriggerBroadcast);
etBroadcastTriggerAction = findViewById(R.id.etBroadcastTriggerAction);
rbBroadcastReceived = findViewById(R.id.rbBroadcastReceived);
rbBroadcastNotReceived = findViewById(R.id.rbBroadcastNotReceived);
tvBroadcastUrl = findViewById(R.id.tvBroadcastUrl);
if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter1) && getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
if(getIntent().getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true))
rbBroadcastReceived.setChecked(true);
else
rbBroadcastNotReceived.setChecked(true);
etBroadcastTriggerAction.setText(getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
}
tvBroadcastUrl.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources().getString(R.string.broadcastListUrl)));
startActivity(browserIntent);
}
});
bBroadcastShowSuggestions.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ActivityManageTriggerBroadcast.this);
builder.setTitle(getResources().getString(R.string.selectBroadcast));
builder.setItems(broadcastSuggestions, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialogInterface, int which)
{
etBroadcastTriggerAction.setText(broadcastSuggestions[which]);
}
});
builder.create().show();
}
});
bSaveTriggerBroadcast.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if(etBroadcastTriggerAction.getText() != null && !StringUtils.isEmpty(etBroadcastTriggerAction.getText().toString()))
{
Intent data = new Intent();
data.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbBroadcastReceived.isChecked());
data.putExtra(ActivityManageRule.intentNameTriggerParameter2, etBroadcastTriggerAction.getText().toString());
ActivityManageTriggerBroadcast.this.setResult(RESULT_OK, data);
finish();
}
else
Toast.makeText(ActivityManageTriggerBroadcast.this, getResources().getString(R.string.enterText), Toast.LENGTH_SHORT).show();
}
});
}
public static String[] broadcastSuggestions = {
"android.accounts.LOGIN_ACCOUNTS_CHANGED",
"android.accounts.action.ACCOUNT_REMOVED",
"android.app.action.ACTION_PASSWORD_CHANGED",
"android.app.action.ACTION_PASSWORD_EXPIRING",
"android.app.action.ACTION_PASSWORD_FAILED",
"android.app.action.ACTION_PASSWORD_SUCCEEDED",
"android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE",
"android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED",
"android.app.action.APP_BLOCK_STATE_CHANGED",
"android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED",
"android.app.action.BUGREPORT_FAILED",
"android.app.action.BUGREPORT_SHARE",
"android.app.action.BUGREPORT_SHARING_DECLINED",
"android.app.action.DATA_SHARING_RESTRICTION_APPLIED",
"android.app.action.DATA_SHARING_RESTRICTION_CHANGED",
"android.app.action.DEVICE_ADMIN_DISABLED",
"android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED",
"android.app.action.DEVICE_ADMIN_ENABLED",
"android.app.action.DEVICE_OWNER_CHANGED",
"android.app.action.INTERRUPTION_FILTER_CHANGED",
"android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL",
"android.app.action.LOCK_TASK_ENTERING",
"android.app.action.LOCK_TASK_EXITING",
"android.app.action.MANAGED_USER_CREATED",
"android.app.action.NETWORK_LOGS_AVAILABLE",
"android.app.action.NEXT_ALARM_CLOCK_CHANGED",
"android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED",
"android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED",
"android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED",
"android.app.action.NOTIFICATION_POLICY_CHANGED",
"android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE",
"android.app.action.PROFILE_OWNER_CHANGED",
"android.app.action.PROFILE_PROVISIONING_COMPLETE",
"android.app.action.SECURITY_LOGS_AVAILABLE",
"android.app.action.SYSTEM_UPDATE_POLICY_CHANGED",
"android.app.action.TRANSFER_OWNERSHIP_COMPLETE",
"android.app.action.USER_ADDED",
"android.app.action.USER_REMOVED",
"android.app.action.USER_STARTED",
"android.app.action.USER_STOPPED",
"android.app.action.USER_SWITCHED",
"android.appwidget.action.APPWIDGET_DELETED",
"android.appwidget.action.APPWIDGET_DISABLED",
"android.appwidget.action.APPWIDGET_ENABLED",
"android.appwidget.action.APPWIDGET_HOST_RESTORED",
"android.appwidget.action.APPWIDGET_RESTORED",
"android.appwidget.action.APPWIDGET_UPDATE",
"android.appwidget.action.APPWIDGET_UPDATE_OPTIONS",
"android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED",
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED",
"android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED",
"android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED",
"android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.adapter.action.DISCOVERY_FINISHED",
"android.bluetooth.adapter.action.DISCOVERY_STARTED",
"android.bluetooth.adapter.action.LOCAL_NAME_CHANGED",
"android.bluetooth.adapter.action.SCAN_MODE_CHANGED",
"android.bluetooth.adapter.action.STATE_CHANGED",
"android.bluetooth.device.action.ACL_CONNECTED",
"android.bluetooth.device.action.ACL_DISCONNECTED",
"android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED",
"android.bluetooth.device.action.ALIAS_CHANGED",
"android.bluetooth.device.action.BATTERY_LEVEL_CHANGED",
"android.bluetooth.device.action.BOND_STATE_CHANGED",
"android.bluetooth.device.action.CLASS_CHANGED",
"android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL",
"android.bluetooth.device.action.CONNECTION_ACCESS_REPLY",
"android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST",
"android.bluetooth.device.action.FOUND",
"android.bluetooth.device.action.MAS_INSTANCE",
"android.bluetooth.device.action.NAME_CHANGED",
"android.bluetooth.device.action.NAME_FAILED",
"android.bluetooth.device.action.PAIRING_CANCEL",
"android.bluetooth.device.action.PAIRING_REQUEST",
"android.bluetooth.device.action.SDP_RECORD",
"android.bluetooth.device.action.SILENCE_MODE_CHANGED",
"android.bluetooth.device.action.UUID",
"android.bluetooth.devicepicker.action.DEVICE_SELECTED",
"android.bluetooth.devicepicker.action.LAUNCH",
"android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT",
"android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED",
"android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED",
"android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED",
"android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.input.profile.action.HANDSHAKE",
"android.bluetooth.input.profile.action.IDLE_TIME_CHANGED",
"android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED",
"android.bluetooth.input.profile.action.REPORT",
"android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS",
"android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED",
"android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED",
"android.content.pm.action.SESSION_COMMITTED",
"android.content.pm.action.SESSION_UPDATED",
"android.hardware.action.NEW_PICTURE",
"android.hardware.action.NEW_VIDEO",
"android.hardware.hdmi.action.OSD_MESSAGE",
"android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS",
"android.hardware.usb.action.USB_ACCESSORY_ATTACHED",
"android.hardware.usb.action.USB_ACCESSORY_DETACHED",
"android.hardware.usb.action.USB_DEVICE_ATTACHED",
"android.hardware.usb.action.USB_DEVICE_DETACHED",
"android.intent.action.ACTION_IDLE_MAINTENANCE_END",
"android.intent.action.ACTION_IDLE_MAINTENANCE_START",
"android.intent.action.ACTION_POWER_CONNECTED",
"android.intent.action.ACTION_POWER_DISCONNECTED",
"android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED",
"android.intent.action.ACTION_SHUTDOWN",
"android.intent.action.AIRPLANE_MODE",
"android.intent.action.ALARM_CHANGED",
"android.intent.action.APPLICATION_RESTRICTIONS_CHANGED",
"android.intent.action.BATTERY_CHANGED",
"android.intent.action.BATTERY_LOW",
"android.intent.action.BATTERY_OKAY",
"android.intent.action.BOOT_COMPLETED",
"android.intent.action.CALL_DISCONNECT_CAUSE",
"android.intent.action.CAMERA_BUTTON",
"android.intent.action.CANCEL_ENABLE_ROLLBACK",
"android.intent.action.CLEAR_DNS_CACHE",
"android.intent.action.CLOSE_SYSTEM_DIALOGS",
"android.intent.action.CONFIGURATION_CHANGED",
"android.intent.action.CONTENT_CHANGED",
"android.intent.action.DATA_SMS_RECEIVED",
"android.intent.action.DATA_STALL_DETECTED",
"android.intent.action.DATE_CHANGED",
"android.intent.action.DEVICE_STORAGE_FULL",
"android.intent.action.DEVICE_STORAGE_LOW",
"android.intent.action.DEVICE_STORAGE_NOT_FULL",
"android.intent.action.DEVICE_STORAGE_OK",
"android.intent.action.DISTRACTING_PACKAGES_CHANGED",
"android.intent.action.DOCK_EVENT",
"android.intent.action.DOWNLOAD_COMPLETE",
"android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED",
"android.intent.action.DREAMING_STARTED",
"android.intent.action.DREAMING_STOPPED",
"android.intent.action.DROPBOX_ENTRY_ADDED",
"android.intent.action.DYNAMIC_SENSOR_CHANGED",
"android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED",
"android.intent.action.EMERGENCY_CALL_STATE_CHANGED",
"android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE",
"android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE",
"android.intent.action.FACTORY_RESET",
"android.intent.action.FETCH_VOICEMAIL",
"android.intent.action.GTALK_CONNECTED",
"android.intent.action.GTALK_DISCONNECTED",
"android.intent.action.HEADSET_PLUG",
"android.intent.action.HEADSET_PLUG",
"android.intent.action.INPUT_METHOD_CHANGED",
"android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION",
"android.intent.action.LOCALE_CHANGED",
"android.intent.action.LOCKED_BOOT_COMPLETED",
"android.intent.action.MANAGE_PACKAGE_STORAGE",
"android.intent.action.MASTER_CLEAR_NOTIFICATION",
"android.intent.action.MEDIA_BAD_REMOVAL",
"android.intent.action.MEDIA_BUTTON",
"android.intent.action.MEDIA_CHECKING",
"android.intent.action.MEDIA_EJECT",
"android.intent.action.MEDIA_MOUNTED",
"android.intent.action.MEDIA_NOFS",
"android.intent.action.MEDIA_REMOVED",
"android.intent.action.MEDIA_SCANNER_FINISHED",
"android.intent.action.MEDIA_SCANNER_SCAN_FILE",
"android.intent.action.MEDIA_SCANNER_STARTED",
"android.intent.action.MEDIA_SHARED",
"android.intent.action.MEDIA_UNMOUNTABLE",
"android.intent.action.MEDIA_UNMOUNTED",
"android.intent.action.MY_PACKAGE_REPLACED",
"android.intent.action.MY_PACKAGE_SUSPENDED",
"android.intent.action.MY_PACKAGE_UNSUSPENDED",
"android.intent.action.NEW_OUTGOING_CALL",
"android.intent.action.NEW_VOICEMAIL",
"android.intent.action.PACKAGES_SUSPENDED",
"android.intent.action.PACKAGES_UNSUSPENDED",
"android.intent.action.PACKAGE_ADDED",
"android.intent.action.PACKAGE_CHANGED",
"android.intent.action.PACKAGE_DATA_CLEARED",
"android.intent.action.PACKAGE_ENABLE_ROLLBACK",
"android.intent.action.PACKAGE_FIRST_LAUNCH",
"android.intent.action.PACKAGE_FULLY_REMOVED",
"android.intent.action.PACKAGE_INSTALL",
"android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION",
"android.intent.action.PACKAGE_NEEDS_VERIFICATION",
"android.intent.action.PACKAGE_REMOVED",
"android.intent.action.PACKAGE_REPLACED",
"android.intent.action.PACKAGE_RESTARTED",
"android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY",
"android.intent.action.PACKAGE_VERIFIED",
"android.intent.action.PHONE_STATE",
"android.intent.action.PROVIDER_CHANGED",
"android.intent.action.PROXY_CHANGE",
"android.intent.action.QUERY_PACKAGE_RESTART",
"android.intent.action.REBOOT",
"android.intent.action.ROLLBACK_COMMITTED",
"android.intent.action.SCREEN_OFF",
"android.intent.action.SCREEN_ON",
"android.intent.action.SERVICE_STATE",
"android.intent.action.SIM_STATE_CHANGED",
"android.intent.action.SPLIT_CONFIGURATION_CHANGED",
"android.intent.action.SUB_DEFAULT_CHANGED",
"android.intent.action.TIMEZONE_CHANGED",
"android.intent.action.TIME_SET",
"android.intent.action.TIME_TICK",
"android.intent.action.UID_REMOVED",
"android.intent.action.UMS_CONNECTED",
"android.intent.action.UMS_DISCONNECTED",
"android.intent.action.USER_PRESENT",
"android.intent.action.USER_UNLOCKED",
"android.intent.action.WALLPAPER_CHANGED",
"android.media.ACTION_SCO_AUDIO_STATE_UPDATED",
"android.media.AUDIO_BECOMING_NOISY",
"android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION",
"android.media.MASTER_MUTE_CHANGED_ACTION",
"android.media.RINGER_MODE_CHANGED",
"android.media.SCO_AUDIO_STATE_CHANGED",
"android.media.STREAM_DEVICES_CHANGED_ACTION",
"android.media.STREAM_MUTE_CHANGED_ACTION",
"android.media.VIBRATE_SETTING_CHANGED",
"android.media.VOLUME_CHANGED_ACTION",
"android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION",
"android.media.action.HDMI_AUDIO_PLUG",
"android.media.action.MICROPHONE_MUTE_CHANGED",
"android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION",
"android.media.action.SPEAKERPHONE_STATE_CHANGED",
"android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED",
"android.media.tv.action.INITIALIZE_PROGRAMS",
"android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT",
"android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED",
"android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED",
"android.net.conn.BACKGROUND_DATA_SETTING_CHANGED",
"android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED",
"android.net.conn.CONNECTIVITY_CHANGE",
"android.net.conn.DATA_ACTIVITY_CHANGE",
"android.net.conn.INET_CONDITION_ACTION",
"android.net.conn.RESTRICT_BACKGROUND_CHANGED",
"android.net.conn.TETHER_STATE_CHANGED",
"android.net.nsd.STATE_CHANGED",
"android.net.scoring.SCORER_CHANGED",
"android.net.scoring.SCORE_NETWORKS",
"android.net.sip.action.SIP_CALL_OPTION_CHANGED",
"android.net.sip.action.SIP_INCOMING_CALL",
"android.net.sip.action.SIP_REMOVE_PROFILE",
"android.net.sip.action.SIP_SERVICE_UP",
"android.net.sip.action.START_SIP",
"android.net.wifi.BATCHED_RESULTS",
"android.net.wifi.NETWORK_IDS_CHANGED",
"android.net.wifi.RSSI_CHANGED",
"android.net.wifi.SCAN_RESULTS",
"android.net.wifi.STATE_CHANGE",
"android.net.wifi.WIFI_STATE_CHANGED",
"android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION",
"android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED",
"android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED",
"android.net.wifi.p2p.CONNECTION_STATE_CHANGE",
"android.net.wifi.p2p.DISCOVERY_STATE_CHANGE",
"android.net.wifi.p2p.PEERS_CHANGED",
"android.net.wifi.p2p.STATE_CHANGED",
"android.net.wifi.p2p.THIS_DEVICE_CHANGED",
"android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED",
"android.net.wifi.supplicant.CONNECTION_CHANGE",
"android.net.wifi.supplicant.STATE_CHANGE",
"android.nfc.action.ADAPTER_STATE_CHANGED",
"android.nfc.action.PREFERRED_PAYMENT_CHANGED",
"android.nfc.action.TRANSACTION_DETECTED",
"android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED",
"android.os.action.DEVICE_IDLE_MODE_CHANGED",
"android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED",
"android.os.action.POWER_SAVE_MODE_CHANGED",
"android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL",
"android.os.action.POWER_SAVE_MODE_CHANGING",
"android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED",
"android.os.action.POWER_SAVE_WHITELIST_CHANGED",
"android.os.action.UPDATE_EMERGENCY_NUMBER_DB",
"android.provider.Telephony.MMS_DOWNLOADED",
"android.provider.Telephony.SECRET_CODE",
"android.provider.Telephony.SIM_FULL",
"android.provider.Telephony.SMS_CARRIER_PROVISION",
"android.provider.Telephony.SMS_CB_RECEIVED",
"android.provider.Telephony.SMS_DELIVER",
"android.provider.Telephony.SMS_RECEIVED",
"android.provider.Telephony.SMS_REJECTED",
"android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED",
"android.provider.Telephony.WAP_PUSH_DELIVER",
"android.provider.Telephony.WAP_PUSH_RECEIVED",
"android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED",
"android.provider.action.EXTERNAL_PROVIDER_CHANGE",
"android.provider.action.SMS_EMERGENCY_CB_RECEIVED",
"android.provider.action.SMS_MMS_DB_CREATED",
"android.provider.action.SMS_MMS_DB_LOST",
"android.provider.action.SYNC_VOICEMAIL",
"android.security.STORAGE_CHANGED",
"android.security.action.KEYCHAIN_CHANGED",
"android.security.action.KEY_ACCESS_CHANGED",
"android.security.action.TRUST_STORE_CHANGED",
"android.service.controls.action.ADD_CONTROL",
"android.settings.ENABLE_MMS_DATA_REQUEST",
"android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED",
"android.speech.tts.engine.TTS_DATA_INSTALLED",
"android.telephony.action.AREA_INFO_UPDATED",
"android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED",
"android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED",
"android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED",
"android.telephony.action.REFRESH_SUBSCRIPTION_PLANS",
"android.telephony.action.SECRET_CODE",
"android.telephony.action.SERVICE_PROVIDERS_UPDATED",
"android.telephony.action.SIM_APPLICATION_STATE_CHANGED",
"android.telephony.action.SIM_CARD_STATE_CHANGED",
"android.telephony.action.SIM_SLOT_STATUS_CHANGED",
"android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED",
"android.telephony.action.SUBSCRIPTION_PLANS_CHANGED",
"android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED",
"android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE",
"android.telephony.euicc.action.OTA_STATUS_CHANGED",
"android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR",
"com.android.intent.action.DISMISS_KEYBOARD_SHORTCUTS",
"com.android.intent.action.SHOW_KEYBOARD_SHORTCUTS",
"com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION",
"com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED"
};
}

View File

@ -263,7 +263,7 @@ public class ActivityManageTriggerNotification extends Activity
etNotificationTitle = (EditText)findViewById(R.id.etNotificationTitle);
etNotificationText = (EditText)findViewById(R.id.etNotificationText);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bSaveTriggerNotification = (Button)findViewById(R.id.bSaveTriggerNotification);
bSaveTriggerNotification = (Button)findViewById(R.id.bSaveActionCloseNotification);
spinnerTitleDirection = (Spinner)findViewById(R.id.spinnerTitleDirection);
spinnerTextDirection = (Spinner)findViewById(R.id.spinnerTextDirection);
tvSelectedApplication = (TextView)findViewById(R.id.etActivityOrActionPath);
@ -272,6 +272,7 @@ public class ActivityManageTriggerNotification extends Activity
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)
@ -312,7 +313,7 @@ public class ActivityManageTriggerNotification extends Activity
{
String app;
if(tvSelectedApplication.getText().toString().equalsIgnoreCase(getResources().getString(R.string.anyApp)))
app = "-1";
app = Trigger.anyAppString;
else
app = tvSelectedApplication.getText().toString();
@ -321,14 +322,6 @@ public class ActivityManageTriggerNotification extends Activity
String textDir = Trigger.getMatchCode(spinnerTextDirection.getSelectedItem().toString());
String text = etNotificationText.getText().toString();
if(edit)
{
editedNotificationTrigger.setTriggerParameter(chkNotificationDirection.isChecked());
editedNotificationTrigger.setTriggerParameter2(app + triggerParameter2Split + titleDir + triggerParameter2Split + title + triggerParameter2Split + textDir + triggerParameter2Split + text);
ActivityManageTriggerNotification.this.setResult(RESULT_OK);
}
else
{
Intent data = new Intent();
data.putExtra(intentNameNotificationDirection, chkNotificationDirection.isChecked());
data.putExtra(intentNameNotificationApp, app);
@ -337,7 +330,6 @@ public class ActivityManageTriggerNotification extends Activity
data.putExtra(intentNameNotificationTextDir, textDir);
data.putExtra(intentNameNotificationText, text);
ActivityManageTriggerNotification.this.setResult(RESULT_OK, data);
}
finish();
}
@ -367,7 +359,7 @@ public class ActivityManageTriggerNotification extends Activity
else
text = "";
if(!app.equals("-1"))
if(!app.equals(Trigger.anyAppString))
tvSelectedApplication.setText(app);
for(int i = 0; i < directions.length; i++)

View File

@ -86,8 +86,8 @@ public class ActivityManageTriggerPhoneCall extends Activity
else
{
Intent data = new Intent();
data.putExtra("triggerParameter", false);
data.putExtra("triggerParameter2", tp2Result);
data.putExtra(ActivityManageRule.intentNameTriggerParameter1, false);
data.putExtra(ActivityManageRule.intentNameTriggerParameter2, tp2Result);
ActivityManageTriggerPhoneCall.this.setResult(RESULT_OK, data);
}

View File

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

View File

@ -0,0 +1,46 @@
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 ActivityManageTriggerTethering extends Activity
{
RadioButton rbTetheringOn, rTetheringOff;
Button bTriggerTetheringSave;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_trigger_tethering);
rbTetheringOn = (RadioButton) findViewById(R.id.rbTetheringOn);
rTetheringOff = (RadioButton)findViewById(R.id.rTetheringOff);
bTriggerTetheringSave = (Button) findViewById(R.id.bTriggerTetheringSave);
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
rbTetheringOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
bTriggerTetheringSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbTetheringOn.isChecked());
setResult(RESULT_OK, response);
finish();
}
});
}
}

View File

@ -1,6 +1,7 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
@ -9,13 +10,13 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
import java.sql.Time;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
@ -26,8 +27,9 @@ public class ActivityManageTriggerTimeFrame extends Activity
CheckBox checkMonday, checkTuesday, checkWednesday, checkThursday, checkFriday, checkSaturday, checkSunday, chkRepeat;
RadioButton radioTimeFrameEntering, radioTimeFrameLeaving;
EditText etRepeatEvery;
TextView tvDaysHint;
public static Trigger editedTimeFrameTrigger = null;
static Trigger editedTimeFrameTrigger = null;
@Override
protected void onCreate(Bundle savedInstanceState)
@ -52,17 +54,18 @@ public class ActivityManageTriggerTimeFrame extends Activity
radioTimeFrameLeaving = (RadioButton)findViewById(R.id.radioTimeFrameLeaving);
chkRepeat = (CheckBox)findViewById(R.id.chkRepeat);
etRepeatEvery = (EditText)findViewById(R.id.etRepeatEvery);
tvDaysHint = (TextView)findViewById(R.id.tvDaysHint);
bSaveTimeFrame.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Time startTime = new Time(0);
TimeObject startTime = new TimeObject();
startTime.setHours(startPicker.getCurrentHour());
startTime.setMinutes(startPicker.getCurrentMinute());
Time stopTime = new Time(0);
TimeObject stopTime = new TimeObject();
stopTime.setHours(stopPicker.getCurrentHour());
stopTime.setMinutes(stopPicker.getCurrentMinute());
@ -152,8 +155,13 @@ public class ActivityManageTriggerTimeFrame extends Activity
}
editedTimeFrameTrigger.setTriggerParameter(radioTimeFrameEntering.isChecked());
editedTimeFrameTrigger.setTriggerParameter2(editedTimeFrameTrigger.getTimeFrame().toTriggerParameter2String());
setResult(RESULT_OK);
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, editedTimeFrameTrigger.getTriggerParameter());
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, editedTimeFrameTrigger.getTriggerParameter2());
setResult(RESULT_OK, response);
finish();
}
});
@ -167,10 +175,41 @@ public class ActivityManageTriggerTimeFrame extends Activity
}
});
if(editedTimeFrameTrigger.getTimeFrame() != null)
if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
editedTimeFrameTrigger = new Trigger();
editedTimeFrameTrigger.setTriggerParameter(getIntent().getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
editedTimeFrameTrigger.setTriggerParameter2(getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
editedTimeFrameTrigger.setTimeFrame(new TimeFrame(editedTimeFrameTrigger.getTriggerParameter2()));
loadVariableIntoGui();
}
TimePicker.OnTimeChangedListener pickerListener = new TimePicker.OnTimeChangedListener()
{
@Override
public void onTimeChanged(TimePicker timePicker, int i, int i1)
{
if(
startPicker.getCurrentHour() > stopPicker.getCurrentHour()
||
(
startPicker.getCurrentHour() == stopPicker.getCurrentHour()
&&
startPicker.getCurrentMinute() >= stopPicker.getCurrentMinute()
)
)
tvDaysHint.setText(getResources().getString(R.string.timeFrameDaysHint));
else
tvDaysHint.setText("");
}
};
startPicker.setOnTimeChangedListener(pickerListener);
stopPicker.setOnTimeChangedListener(pickerListener);
// Perform check once
pickerListener.onTimeChanged(null, 0, 0);
}
private void loadVariableIntoGui()
{
startPicker.setCurrentHour(editedTimeFrameTrigger.getTimeFrame().getTriggerTimeStart().getHours());
@ -219,5 +258,4 @@ public class ActivityManageTriggerTimeFrame extends Activity
etRepeatEvery.setText(String.valueOf(editedTimeFrameTrigger.getTimeFrame().getRepetition()));
}
}
}

View File

@ -224,7 +224,7 @@ public class ActivityPermissions extends Activity
}
}
protected static void addToArrayListUnique(String value, ArrayList<String> list)
public static void addToArrayListUnique(String value, List<String> list)
{
if (!list.contains(value))
list.add(value);
@ -250,7 +250,7 @@ public class ActivityPermissions extends Activity
}
else if(s.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || s.equalsIgnoreCase(permissionNameGoogleActivityDetection))
{
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid))
if (!havePermission(s, context))
return true;
}
@ -353,11 +353,18 @@ public class ActivityPermissions extends Activity
if(!havePermission(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, workingContext))
addToArrayListUnique(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, requiredPermissions);
for(Profile p : Profile.getProfileCollection())
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
}
if (!onlyGeneral)
{
for (Rule rule : Rule.getRuleCollection())
{
for (String singlePermission : getPermissionsForRule(rule))
{
if (!havePermission(singlePermission, workingContext))
{
if (
@ -374,7 +381,7 @@ public class ActivityPermissions extends Activity
}
else if (singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection))
{
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
if (!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid))
addToArrayListUnique(singlePermission, requiredPermissions);
}
else
@ -382,6 +389,7 @@ public class ActivityPermissions extends Activity
}
}
}
}
/*
Not all permissions need to be asked for.
@ -518,6 +526,9 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.MODIFY_AUDIO_SETTINGS, requiredPermissions);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
addToArrayListUnique(Manifest.permission.ACCESS_NOTIFICATION_POLICY, requiredPermissions);
Profile targetProfile = Profile.getByName(action.getParameter2());
if(targetProfile.changeIncomingCallsRingtone || targetProfile.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case disableScreenRotation:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@ -527,9 +538,13 @@ public class ActivityPermissions extends Activity
break;
case playMusic:
break;
case controlMediaPlayback:
// addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions);
// addToArrayListUnique(Manifest.permission.MEDIA_CONTENT_CONTROL, requiredPermissions);
break;
case sendTextMessage:
addToArrayListUnique(Manifest.permission.SEND_SMS, requiredPermissions);
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case setAirplaneMode:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@ -588,7 +603,7 @@ public class ActivityPermissions extends Activity
// addToArrayListUnique("android.permission.TETHER_PRIVILEGED", requiredPermissions);
break;
case speakText:
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case startOtherActivity:
if(
@ -608,7 +623,7 @@ public class ActivityPermissions extends Activity
break;
case triggerUrl:
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
checkPermissionsInVariableUse(action.getParameter2(), requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case turnBluetoothOff:
addToArrayListUnique(Manifest.permission.BLUETOOTH_ADMIN, requiredPermissions);
@ -649,6 +664,9 @@ public class ActivityPermissions extends Activity
case playSound:
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case closeNotification:
addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions);
break;
case turnScreenOnOrOff:
if(action.getParameter1())
addToArrayListUnique(Manifest.permission.WAKE_LOCK, requiredPermissions);
@ -852,6 +870,32 @@ public class ActivityPermissions extends Activity
case Manifest.permission.READ_EXTERNAL_STORAGE:
for(String ruleName : getRulesUsing(Action.Action_Enum.playSound))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.changeSoundProfile))
{
Rule tempRule = Rule.getByName(ruleName);
if(tempRule != null)
{
for (Action a : tempRule.getActionSet())
{
if (a.getAction().equals(Action.Action_Enum.changeSoundProfile))
{
Profile p = Profile.getByName(a.getParameter2());
if (p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
}
}
}
}
for(Profile p : Profile.getProfileCollection())
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
{
usingElements.add(String.format(getResources().getString(R.string.profileXrequiresThis), p.getName()));
}
}
break;
case Manifest.permission.BIND_DEVICE_ADMIN:
for(String ruleName : getRulesUsing(Action.Action_Enum.turnScreenOnOrOff))
@ -860,6 +904,9 @@ public class ActivityPermissions extends Activity
case Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS:
usingElements.add(getResources().getString(R.string.recommendedForBetterReliability));
break;
case Manifest.permission.QUERY_ALL_PACKAGES:
usingElements.add(getResources().getString(R.string.queryAllPackages));
break;
}
return usingElements;
@ -1150,7 +1197,7 @@ public class ActivityPermissions extends Activity
}
}
static ArrayList<String> checkPermissionsInVariableUse(String text, ArrayList<String> permsList)
static ArrayList<String> getPermissionsForVariablesInUse(String text, ArrayList<String> permsList)
{
/*
[uniqueid]

View File

@ -18,7 +18,7 @@ public class ActivitySettings extends PreferenceActivity
super.onCreate(savedInstanceState);
addPreferencesFromResource(layout.activity_settings);
if(BuildConfig.FLAVOR.equals("apkFlavor"))
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_apk))
{
chkPrefUpdateCheck = (CheckBoxPreference) findPreference("automaticUpdateCheck");
chkPrefUpdateCheck.setEnabled(true);

View File

@ -28,10 +28,12 @@ import androidx.core.app.NotificationManagerCompat;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider;
import com.jens.automation2.receivers.DateTimeListener;
import com.jens.automation2.receivers.PackageReplacedReceiver;
import com.jens.automation2.receivers.PhoneStatusListener;
import java.util.Calendar;
import java.util.Set;
@SuppressLint("NewApi")
public class AutomationService extends Service implements OnInitListener
@ -41,8 +43,18 @@ public class AutomationService extends Service implements OnInitListener
protected final static int notificationIdRestrictions = 1005;
protected final static int notificationIdLocationRestriction = 1006;
final static String NOTIFICATION_CHANNEL_ID = "com.jens.automation2";
final static String channelName = "Service notification";
public static final String flavor_name_apk = "apkFlavor";
public static final String flavor_name_fdroid = "fdroidFlavor";
public static final String flavor_name_googleplay = "googlePlayFlavor";
final static String NOTIFICATION_CHANNEL_ID_SERVICE = "com.jens.automation2_service";
final static String NOTIFICATION_CHANNEL_NAME_SERVICE = "Service notification";
final static String NOTIFICATION_CHANNEL_ID_FUNCTIONALITY = "com.jens.automation2_functionality";
final static String NOTIFICATION_CHANNEL_NAME_FUNCTIONALITY = "Functionality information";
final static String NOTIFICATION_CHANNEL_ID_RULES = "com.jens.automation2_rules";
final static String NOTIFICATION_CHANNEL_NAME_RULES = "Rule notifications";
protected static Notification myNotification;
protected static NotificationCompat.Builder notificationBuilder = null;
@ -51,6 +63,8 @@ public class AutomationService extends Service implements OnInitListener
protected Calendar lockSoundChangesEnd = null;
protected boolean isRunning;
protected static AutomationService centralInstance = null;
public void nullLockSoundChangesEnd()
{
lockSoundChangesEnd = null;
@ -65,7 +79,6 @@ public class AutomationService extends Service implements OnInitListener
lockSoundChangesEnd = Calendar.getInstance();
lockSoundChangesEnd.add(Calendar.MINUTE, Settings.lockSoundChangesInterval);
// ActivityMainScreen.getActivityMainScreenInstance().updateMainScreen();
}
public void checkLockSoundChangesTimeElapsed()
@ -89,8 +102,6 @@ public class AutomationService extends Service implements OnInitListener
return myLocationProvider;
}
protected static AutomationService centralInstance = null;
public static AutomationService getInstance()
{
return centralInstance;
@ -109,18 +120,6 @@ public class AutomationService extends Service implements OnInitListener
public boolean checkStartupRequirements(Context context, boolean startAtBoot)
{
// if (!ActivityPermissions.havePermission(ActivityPermissions.writeExternalStoragePermissionName, AutomationService.this))
// {
// /*
// Don't have permission to access external storage. This is a show stopper as
// the configuration file is stored on external storage.
// */
// Miscellaneous.logEvent("e", "Permission", "Don't have permission to access external storage. Will request it now.", 4);
//// Toast.makeText(AutomationService.this, getResources().getString(R.string.appRequiresPermissiontoAccessExternalStorage), Toast.LENGTH_LONG).show();
// ActivityPermissions.requestSpecificPermission(ActivityPermissions.writeExternalStoragePermissionName);
// return false;
// }
if(Build.VERSION.SDK_INT >= 28)
{
if (!ActivityPermissions.havePermission(Manifest.permission.FOREGROUND_SERVICE, AutomationService.this))
@ -135,9 +134,14 @@ public class AutomationService extends Service implements OnInitListener
}
}
if (PointOfInterest.getPointOfInterestCollection() == null | PointOfInterest.getPointOfInterestCollection().size() == 0
|
Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0
if (
PointOfInterest.getPointOfInterestCollection() == null
||
PointOfInterest.getPointOfInterestCollection().size() == 0
||
Rule.getRuleCollection() == null
||
Rule.getRuleCollection().size() == 0
)
{
if (startAtBoot)
@ -173,7 +177,7 @@ public class AutomationService extends Service implements OnInitListener
}
//if still no POIs...
if (Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0)
if (Rule.getRuleCollection() == null || Rule.getRuleCollection().size() == 0)
{
Miscellaneous.logEvent("w", "AutomationService", context.getResources().getString(R.string.serviceWontStart), 1);
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
@ -194,18 +198,21 @@ public class AutomationService extends Service implements OnInitListener
{
Bundle b = intent.getExtras();
startAtBoot = b.getBoolean("startAtBoot", false);
if(startAtBoot)
Settings.deviceStartDone = false;
}
if (checkStartupRequirements(this, startAtBoot))
{
Miscellaneous.logEvent("i", "Service", this.getResources().getString(R.string.logServiceStarting) + " VERSION_CODE: " + BuildConfig.VERSION_CODE + ", VERSION_NAME: " + BuildConfig.VERSION_NAME + ", flavor: " + BuildConfig.FLAVOR, 1);
Miscellaneous.logEvent("i", "Service", ActivityMaintenance.getSystemInfo(), 1);
Miscellaneous.logEvent("i", "Service", ActivityControlCenter.getSystemInfo(), 1);
startUpRoutine();
Intent myIntent = new Intent(this, ActivityMainTabLayout.class);
myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0);
notificationBuilder = createDefaultNotificationBuilder();
notificationBuilder = createServiceNotificationBuilder();
updateNotification();
@ -213,13 +220,17 @@ public class AutomationService extends Service implements OnInitListener
ActivityMainScreen.updateMainScreen();
this.isRunning = true;
Miscellaneous.logEvent("i", "Service", this.getResources().getString(R.string.serviceStarted) + " VERSION_CODE: " + BuildConfig.VERSION_CODE + ", VERSION_NAME: " + BuildConfig.VERSION_NAME + ", flavor: " + BuildConfig.FLAVOR, 1);
Toast.makeText(this, this.getResources().getString(R.string.serviceStarted), Toast.LENGTH_LONG).show();
// ********** Test area **********
// Miscellaneous.logEvent("i", "setNetworkType", "bin hier.", 3);
// Actions.setData(true);
// ********** Test area **********
/*
On normal phones the app is supposed to automatically restart in case of any problems.
In the emulator we want it to stop to be able to better pinpoint the root cause.
*/
if(Miscellaneous.isAndroidEmulator())
return START_NOT_STICKY;
else
return START_STICKY;
}
else
@ -241,8 +252,6 @@ public class AutomationService extends Service implements OnInitListener
reloadSettings, reloadPointsOfInterest, reloadRules, updateNotification
}
;
public void serviceInterface(serviceCommands command)
{
Miscellaneous.logEvent("i", "Bind", "Ahhhh, customers... How can I help you?", 5);
@ -282,6 +291,8 @@ public class AutomationService extends Service implements OnInitListener
myLocationProvider.applySettingsAndRules();
ReceiverCoordinator.applySettingsAndRules();
DateTimeListener.reloadAlarms();
}
@Override
@ -310,18 +321,29 @@ public class AutomationService extends Service implements OnInitListener
private void startUpRoutine()
{
Settings.serviceStartDone = false;
checkForTtsEngine();
checkForPermissions();
checkForRestrictedFeatures();
checkForMissingBackgroundLocationPermission();
Actions.context = this;
Actions.autoMationServerRef = this;
Actions.automationServerRef = this;
startLocationProvider();
ReceiverCoordinator.startAllReceivers();
PackageReplacedReceiver.setHasServiceBeenRunning(true, this);
for(Rule r : Rule.getRuleCollection())
{
if(r.getsGreenLight(AutomationService.this))
r.activate(AutomationService.this, false);
}
Settings.serviceStartDone = true;
Settings.deviceStartDone = true;
}
protected void startLocationProvider()
@ -365,9 +387,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Features disabled because of rule " + rule, 5);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(1010, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
Miscellaneous.createDismissibleNotificationWithDelay(1010, null, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
}
@ -389,9 +411,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Background location disabled because Google to blame.", 5);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(3300, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
Miscellaneous.createDismissibleNotificationWithDelay(3300, null, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
}
@ -411,9 +433,9 @@ public class AutomationService extends Service implements OnInitListener
Miscellaneous.logEvent("w", "Features disabled", "Background location disabled because Google to blame.", 5);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(2200, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
Miscellaneous.createDismissibleNotificationWithDelay(2200, null, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, pi);
}
}
@ -449,6 +471,8 @@ public class AutomationService extends Service implements OnInitListener
ttsEngine.shutdown();
PackageReplacedReceiver.setHasServiceBeenRunning(false, this);
centralInstance = null;
}
protected static Builder createDefaultNotificationBuilderOld()
@ -482,7 +506,7 @@ public class AutomationService extends Service implements OnInitListener
return builder;
}
protected static NotificationCompat.Builder createDefaultNotificationBuilder()
protected static NotificationCompat.Builder createServiceNotificationBuilder()
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -490,14 +514,14 @@ public class AutomationService extends Service implements OnInitListener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_LOW);
// chan.setLightColor(Color.BLUE);
chan.enableVibration(false);
chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel channel = Miscellaneous.getNotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE);
// channel.setLightColor(Color.BLUE);
channel.enableVibration(false);
channel.setSound(null, null);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID_SERVICE);
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
@ -542,11 +566,11 @@ public class AutomationService extends Service implements OnInitListener
if(activePoi == null)
{
PointOfInterest closestPoi = PointOfInterest.getClosestPOI(instance.getLocationProvider().getCurrentLocation());
bodyText = AutomationService.getInstance().getResources().getString(R.string.activePoi) + ": " + AutomationService.getInstance().getResources().getString(R.string.none) + "\n" + AutomationService.getInstance().getResources().getString(R.string.closestPoi) + ": " + closestPoi.getName() + lastRuleString;
bodyText = AutomationService.getInstance().getResources().getString(R.string.activePoi) + " " + AutomationService.getInstance().getResources().getString(R.string.none) + "\n" + AutomationService.getInstance().getResources().getString(R.string.closestPoi) + ": " + closestPoi.getName() + lastRuleString;
}
else
{
bodyText = AutomationService.getInstance().getResources().getString(R.string.activePoi) + ": " + activePoi.getName() + lastRuleString;
bodyText = AutomationService.getInstance().getResources().getString(R.string.activePoi) + " " + activePoi.getName() + lastRuleString;
}
}
catch(NullPointerException e)
@ -576,7 +600,7 @@ public class AutomationService extends Service implements OnInitListener
String textToDisplay = bodyText + " " + lastRuleString;
if(notificationBuilder == null)
notificationBuilder = createDefaultNotificationBuilder();
notificationBuilder = createServiceNotificationBuilder();
notificationBuilder.setContentText(textToDisplay);
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));

View File

@ -8,7 +8,7 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -16,6 +16,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@ -23,6 +25,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.Settings.Secure;
import android.telephony.PhoneNumberUtils;
@ -72,8 +75,10 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@ -83,7 +88,10 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@ -98,13 +106,10 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.documentfile.provider.DocumentFile;
import static android.provider.CalendarContract.CalendarCache.URI;
import static com.jens.automation2.AutomationService.NOTIFICATION_CHANNEL_ID;
import static com.jens.automation2.AutomationService.channelName;
public class Miscellaneous extends Service
{
protected static String writeableFolderStringCache = null;
@ -476,6 +481,8 @@ public class Miscellaneous extends Service
return !haystack.equalsIgnoreCase(needle);
case Trigger.directionContains:
return haystack.toLowerCase().contains(needle.toLowerCase());
case Trigger.directionNotContains:
return !haystack.toLowerCase().contains(needle.toLowerCase());
case Trigger.directionStartsWith:
return haystack.toLowerCase().startsWith(needle.toLowerCase());
case Trigger.directionEndsWith:
@ -485,7 +492,7 @@ public class Miscellaneous extends Service
}
}
public static int compareTimes(Time time1, Time time2)
public static int compareTimes(TimeObject time1, TimeObject time2)
{
// Miscellaneous.logEvent("i", "TimeCompare", "To compare: " + time1.toString() + " / " + time2.toString());
@ -630,6 +637,8 @@ public class Miscellaneous extends Service
}
if(source.contains("[notificationTitle]"))
{
if(NotificationListener.getLastNotification() != null)
{
String notificationTitle = NotificationListener.getLastNotification().getTitle();
@ -637,12 +646,20 @@ public class Miscellaneous extends Service
source = source.replace("[notificationTitle]", notificationTitle);
else
{
source = source.replace("notificationTitle unknown", notificationTitle);
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationTitle was empty.", 3);
}
}
else
{
source = source.replace("[notificationTitle]", "notificationTitle unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
if(source.contains("[notificationText]"))
{
if(NotificationListener.getLastNotification() != null)
{
String notificationText = NotificationListener.getLastNotification().getText();
@ -650,10 +667,16 @@ public class Miscellaneous extends Service
source = source.replace("[notificationText]", notificationText);
else
{
source = source.replace("notificationText unknown", notificationText);
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "notificationText was empty.", 3);
}
}
else
{
source = source.replace("[notificationText]", "notificationText unknown");
Miscellaneous.logEvent("w", "Variable replacement", "lastNotification was empty.", 3);
}
}
// Miscellaneous.logEvent("i", "URL after replace", source);
@ -689,14 +712,6 @@ public class Miscellaneous extends Service
}
});
// alertDialog.setNegativeButton(context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener()
// {
// public void onClick(DialogInterface dialog, int whichButton)
// {
// // Canceled.
// }
// });
return alertDialog.create();
}
@ -877,7 +892,7 @@ public class Miscellaneous extends Service
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void createDismissableNotificationWithDelay(long delay, String textToDisplay, int notificationId, PendingIntent pendingIntent)
public static void createDismissibleNotificationWithDelay(long delay, String title, String textToDisplay, int notificationId, String notificationChannelId, PendingIntent pendingIntent)
{
/*
Now what's this about?
@ -903,7 +918,7 @@ public class Miscellaneous extends Service
catch(Exception e)
{}
createDismissableNotification(textToDisplay, notificationId, pendingIntent);
createDismissibleNotification(title, textToDisplay, notificationId, true, notificationChannelId, pendingIntent);
return null;
}
@ -924,40 +939,88 @@ public class Miscellaneous extends Service
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void createDismissableNotification(String textToDisplay, int notificationId, PendingIntent pendingIntent)
public static void createDismissibleNotification(String title, String textToDisplay, int notificationId, boolean vibrate, String notificationChannelId, PendingIntent pendingIntent)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
createDismissableNotificationSdk26(textToDisplay, notificationId, pendingIntent);
createDismissibleNotificationSdk26(title, textToDisplay, notificationId, vibrate, notificationChannelId, pendingIntent);
return;
}
NotificationManager mNotificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder dismissableNotificationBuilder = createDismissableNotificationBuilder(pendingIntent);
dismissableNotificationBuilder.setContentText(textToDisplay);
dismissableNotificationBuilder.setContentIntent(pendingIntent);
dismissableNotificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
dismissableNotificationBuilder.setAutoCancel(true);
NotificationCompat.Builder dismissibleNotificationBuilder = createDismissibleNotificationBuilder(vibrate, notificationChannelId, pendingIntent);
Notification dismissableNotification = dismissableNotificationBuilder.build();
if(title == null)
dismissibleNotificationBuilder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
else
dismissibleNotificationBuilder.setContentTitle(title);
mNotificationManager.notify(notificationId, dismissableNotification);
dismissibleNotificationBuilder.setContentText(textToDisplay);
dismissibleNotificationBuilder.setContentIntent(pendingIntent);
dismissibleNotificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
dismissibleNotificationBuilder.setAutoCancel(true);
/*NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle("Notification!") // title for notification
.setContentText("Hello word") // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, dismissableNotification);*/
if(notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_RULES))
dismissibleNotificationBuilder.setSmallIcon(R.drawable.info);
Notification dismissibleNotification = dismissibleNotificationBuilder.build();
mNotificationManager.notify(notificationId, dismissibleNotification);
}
static void createDismissableNotificationSdk26(String textToDisplay, int notificationId, PendingIntent pendingIntent)
@RequiresApi(api = Build.VERSION_CODES.O)
static NotificationChannel findExistingChannel(List<NotificationChannel> channels, String channelId)
{
for(NotificationChannel c : channels)
{
if(c.getId().equals(channelId))
return c;
}
return null;
}
@RequiresApi(api = Build.VERSION_CODES.O)
static NotificationChannel getNotificationChannel(String channelId)
{
NotificationManager nm = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
List<NotificationChannel> channels = nm.getNotificationChannels();
if(!Settings.hasBeenDone(Settings.constNotificationChannelCleanupApk118) && BuildConfig.VERSION_CODE < 120)
{
// Perform a one-time cleanup of notification channels as they have been redesigned.
for(NotificationChannel c : channels)
nm.deleteNotificationChannel(c.getId());
Settings.considerDone(Settings.constNotificationChannelCleanupApk118);
Settings.writeSettings(Miscellaneous.getAnyContext());
}
NotificationChannel channel = findExistingChannel(channels, channelId);
if(channel == null)
{
switch (channelId)
{
case AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, AutomationService.NOTIFICATION_CHANNEL_NAME_SERVICE, NotificationManager.IMPORTANCE_LOW);
break;
case AutomationService.NOTIFICATION_CHANNEL_ID_FUNCTIONALITY:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_FUNCTIONALITY, AutomationService.NOTIFICATION_CHANNEL_NAME_FUNCTIONALITY, NotificationManager.IMPORTANCE_HIGH);
break;
case AutomationService.NOTIFICATION_CHANNEL_ID_RULES:
channel = new NotificationChannel(AutomationService.NOTIFICATION_CHANNEL_ID_RULES, AutomationService.NOTIFICATION_CHANNEL_NAME_RULES, NotificationManager.IMPORTANCE_HIGH);
break;
default:
break;
}
}
return channel;
}
static void createDismissibleNotificationSdk26(String title, String textToDisplay, int notificationId, boolean vibrate, String notificationChannelId, PendingIntent pendingIntent)
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -965,29 +1028,44 @@ public class Miscellaneous extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Functionality warnings", NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE);
chan.enableVibration(false);
// chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel notificationChannel = getNotificationChannel(notificationChannelId);
// notificationChannel.setLightColor(Color.BLUE);
notificationChannel.enableVibration(vibrate);
try
{
Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// Uri notificationSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE+ "://" +mContext.getPackageName()+"/"+R.raw.apple_ring));
// Ringtone r = RingtoneManager.getRingtone(Miscellaneous.getAnyContext(), notification);
AudioAttributes.Builder b = new AudioAttributes.Builder();
b.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN);
notificationChannel.setSound(notificationSound, b.build());
}
catch (Exception e)
{
Miscellaneous.logEvent("i", "Notification", Log.getStackTraceString(e), 2);
}
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), notificationChannel.getId());
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
// builder.setCategory(Notification.CATEGORY_SERVICE);
builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(pendingIntent);
if(title == null)
builder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
else
builder.setContentTitle(title);
builder.setOnlyAlertOnce(true);
if(Settings.showIconWhenServiceIsRunning)
if(Settings.showIconWhenServiceIsRunning && notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.ic_launcher);
else if(!notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.info);
builder.setContentText(textToDisplay);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
@ -995,7 +1073,6 @@ public class Miscellaneous extends Service
NotificationManager notificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
// Intent notifyIntent = new Intent(context, notification.class);
// notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//
@ -1017,7 +1094,7 @@ public class Miscellaneous extends Service
// notificationManager.notify(1, notification);
}
protected static NotificationCompat.Builder createDismissableNotificationBuilder(PendingIntent myPendingIntent)
protected static NotificationCompat.Builder createDismissibleNotificationBuilder(boolean vibrate, String notificationChannelId, PendingIntent myPendingIntent)
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
@ -1025,14 +1102,14 @@ public class Miscellaneous extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE);
// chan.enableVibration(false);
// chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
NotificationChannel notificationChannel = getNotificationChannel(notificationChannelId);
// notificationChannel.setLightColor(Color.BLUE);
notificationChannel.enableVibration(vibrate);
// notificationChannel.setSound(null, null);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), notificationChannelId);
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
@ -1110,7 +1187,8 @@ public class Miscellaneous extends Service
public static double round(double value, int places)
{
if (places < 0) throw new IllegalArgumentException();
if (places < 0)
throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(Double.toString(value));
bd = bd.setScale(places, RoundingMode.HALF_UP);
@ -1122,7 +1200,7 @@ public class Miscellaneous extends Service
Cursor cursor = null;
try
{
String[] proj = { MediaStore.Images.Media.DATA };
String[] proj = { MediaStore.Images.Media.DATA, MediaStore.Audio.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
@ -1142,6 +1220,114 @@ public class Miscellaneous extends Service
}
}
public static String getRealPathFromURI2(final Context context, final Uri uri)
{
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
{
// ExternalStorageProvider
if (isExternalStorageDocument(uri))
{
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type))
{
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri))
{
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri))
{
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type))
{
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
else if ("video".equals(type))
{
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
else if ("audio".equals(type))
{
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme()))
{
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme()))
{
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs)
{
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try
{
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst())
{
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
}
finally
{
if (cursor != null)
cursor.close();
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri)
{
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri)
{
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri)
{
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static Method getClassMethodReflective(String className, String methodName)
{
Class foundClass = null;
@ -1434,7 +1620,7 @@ public class Miscellaneous extends Service
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
if (BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor"))
if (BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))
{
if(checkExistingRules)
{
@ -1593,4 +1779,118 @@ public class Miscellaneous extends Service
return formattedDate;
}
public static boolean arraySearch(String[] haystack, String needle, boolean caseSensitive, boolean matchFullLine)
{
if(matchFullLine)
{
if(caseSensitive)
{
for (String s : haystack)
{
if (s.equals(needle))
return true;
}
}
else
{
for (String s : haystack)
{
if (s.toLowerCase().equals(needle.toLowerCase()))
return true;
}
}
}
else
{
if(caseSensitive)
{
for (String s : haystack)
{
if (s.contains(needle))
return true;
}
}
else
{
for (String s : haystack)
{
if (s.toLowerCase().contains(needle.toLowerCase()))
return true;
}
}
}
return false;
}
public static boolean arraySearch(ArrayList<String> requestList, String needle, boolean caseSensitive, boolean matchFullLine)
{
return arraySearch(requestList.toArray(new String[requestList.size()]), needle, caseSensitive, matchFullLine);
}
/**
* Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
* @param context Context reference to get the TelephonyManager instance from
* @return country code or null
*/
public static String getUserCountry(Context context)
{
try
{
final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final String simCountry = tm.getSimCountryIso();
if (simCountry != null && simCountry.length() == 2)
{ // SIM country code is available
return simCountry.toLowerCase(Locale.US);
}
else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA)
{ // device is not 3G (would be unreliable)
String networkCountry = tm.getNetworkCountryIso();
if (networkCountry != null && networkCountry.length() == 2)
{ // network country code is available
return networkCountry.toLowerCase(Locale.US);
}
}
}
catch (SecurityException se)
{
return "unknown";
}
catch (Exception e)
{ }
return null;
}
public static String checksumSha(String filepath) throws IOException
{
try
{
MessageDigest md = null;
md = MessageDigest.getInstance("SHA-256");
// file hashing with DigestInputStream
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md))
{
while (dis.read() != -1)
; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
StringBuilder result = new StringBuilder();
for (byte b : md.digest())
{
result.append(String.format("%02x", b));
}
return result.toString();
}
catch (NoSuchAlgorithmException e)
{
Miscellaneous.logEvent("e", "shaChecksum", Log.getStackTraceString(e), 2);
}
return null;
}
}

View File

@ -4,10 +4,12 @@ import android.app.NotificationManager;
import android.content.ContentValues;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
@ -306,29 +308,31 @@ public class Profile implements Comparable<Profile>
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, ringtoneFile.getAbsolutePath());
// values.put(MediaStore.MediaColumns.TITLE, context.getResources().getString(R.string.app_name) + " ringtone");
// values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName().replace(".mp3", "").replace(".", ""));
values.put(MediaStore.MediaColumns.TITLE, ringtoneFile.getName());
// values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, ringtoneFile.length());
// values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, ringtoneType == RingtoneManager.TYPE_RINGTONE);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, ringtoneType == RingtoneManager.TYPE_NOTIFICATION);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if(existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
Uri newRingTone = context.getContentResolver().insert(existingRingTone, values);
try
{
Uri newRingTone = null;
//TODO: This part needs to be made compatible with Android 11 and above.
if(Build.VERSION.SDK_INT > 30)
{
Uri existingRingTone = MediaStore.Audio.Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
if (existingRingTone != null)
context.getContentResolver().delete(existingRingTone, MediaStore.MediaColumns.DATA + "=\"" + ringtoneFile.getAbsolutePath() + "\"", null);
newRingTone = context.getContentResolver().insert(existingRingTone, values);
}
RingtoneManager.setActualDefaultRingtoneUri(context, ringtoneType, newRingTone);
Miscellaneous.logEvent("i", "Profile", "Ringtone set to: " + newRingTone.toString(), 1);
// Ringtone tone = RingtoneManager.getRingtone(context, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
// tone.play();
return true;
}
catch (Throwable t)
@ -454,29 +458,17 @@ public class Profile implements Comparable<Profile>
public boolean delete(Context context)
{
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.profileActive))
Rule usingRule = this.isInUseByRules();
if(usingRule != null)
{
for (Rule rule : Rule.findRuleCandidatesByTriggerProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), usingRule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
{
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
{
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
return false;
}
}
else
{
profileCollection.remove(this);
return XmlFileInterface.writeFile();
}
return false;
}
private boolean plausibilityCheck()
@ -636,13 +628,33 @@ public class Profile implements Comparable<Profile>
return false;
}
// if(changeIncomingCallsRingtone)
// {
// if (incomingCallsRingtone != null)
// {
// applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
// }
// }
/*if (changeIncomingCallsRingtone)
{
if (incomingCallsRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE);
if (ringtone_uri != null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
Ringtone currentRingtone = RingtoneManager.getRingtone(context, ringtone_uri);
String title = currentRingtone.getTitle(context);
*//* Ringtone desiredRingtone = RingtoneManager.getRingtone(context, Uri.fromFile(notificationRingtone));
boolean result = currentRingtone.equals(desiredRingtone);*//*
Uri desired_ringtone = MediaStore.Audio.Media.getContentUriForPath(incomingCallsRingtone.getAbsolutePath());
// File currentRingtoneFile = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(ringtone_uri.getPath());
String desiredChecksum = Miscellaneous.checksumSha(incomingCallsRingtone.getAbsolutePath());
if (!currentChecksum.equals(desiredChecksum))
return false;
}
}
}*/
if (changeVibrateWhenRinging)
{
@ -660,9 +672,31 @@ public class Profile implements Comparable<Profile>
}
}
// if(changeNotificationRingtone)
// if(notificationRingtone != null)
// applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
/*if (changeNotificationRingtone)
{
if (notificationRingtone != null)
{
Uri ringtone_uri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION);
if (ringtone_uri == null)
{
// if ringtone_uri is null get Default Ringtone
ringtone_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
File currentRingtone = new File(Settings.System.DEFAULT_NOTIFICATION_URI.getPath());
// File currentRingtone = new File(Miscellaneous.getRealPathFromURI(context, ringtone_uri));
String currentChecksum = Miscellaneous.checksumSha(currentRingtone.getAbsolutePath());
String desiredChecksum = Miscellaneous.checksumSha(notificationRingtone.getAbsolutePath());
if(!currentChecksum.equals(desiredChecksum))
return false;
}
else
return false;
}
}*/
if(changeScreenLockUnlockSound)
{
@ -730,4 +764,11 @@ public class Profile implements Comparable<Profile>
return this.oldName;
}
public static Profile getLastActivatedProfile()
{
if(Profile.profileActivationHistory != null && Profile.profileActivationHistory.size() > 0)
return Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
else
return null;
}
}

View File

@ -5,6 +5,7 @@ import android.util.Log;
import com.jens.automation2.location.CellLocationChangedReceiver;
import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.DateTimeListener;
import com.jens.automation2.receivers.AutomationListenerInterface;
import com.jens.automation2.receivers.BatteryReceiver;
@ -12,9 +13,12 @@ import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener;
import com.jens.automation2.receivers.MediaPlayerListener;
import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
import com.jens.automation2.receivers.TimeZoneListener;
import androidx.annotation.RequiresApi;
@ -51,9 +55,13 @@ public class ReceiverCoordinator
HeadphoneJackListener.class,
//NfcReceiver.class,
NoiseListener.class,
//NotificationListener.class,
PhoneStatusListener.class,
ProcessListener.class,
TimeZoneListener.class
MediaPlayerListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class,
TetheringReceiver.class
};
}
catch (ClassNotFoundException e)
@ -62,6 +70,7 @@ public class ReceiverCoordinator
DateTimeListener.class,
BatteryReceiver.class,
BluetoothReceiver.class,
BroadcastListener.class,
ConnectivityReceiver.class,
DeviceOrientationListener.class,
HeadphoneJackListener.class,
@ -69,7 +78,9 @@ public class ReceiverCoordinator
NoiseListener.class,
PhoneStatusListener.class,
ProcessListener.class,
TimeZoneListener.class
ScreenStateReceiver.class,
TimeZoneListener.class,
TetheringReceiver.class
};
}
}
@ -132,12 +143,6 @@ public class ReceiverCoordinator
Miscellaneous.logEvent("w", "Error in new model", Log.getStackTraceString(e), 3);
}
// if(Settings.useAccelerometerForPositioning && !Miscellaneous.isAndroidEmulator())
// {
// accelerometerHandler = new AccelerometerHandler();
// mySensorActivity = new SensorActivity(this);
// }
// startPhoneStateListener
PhoneStatusListener.startPhoneStatusListener(AutomationService.getInstance()); // also used to mute anouncements during calls
@ -163,13 +168,20 @@ public class ReceiverCoordinator
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.noiseLevel))
NoiseListener.startNoiseListener(AutomationService.getInstance());
// startNoiseListener
// startBroadcastListener
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.broadcastReceived))
BroadcastListener.getInstance().startListener(AutomationService.getInstance());
// startProcessListener
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.process_started_stopped))
ProcessListener.startProcessListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.deviceOrientation))
DeviceOrientationListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering))
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
try
{
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
@ -182,13 +194,17 @@ public class ReceiverCoordinator
// Nothing to do, just not starting this one.
}
//startBluetoothReceiver
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.bluetoothConnection))
BluetoothReceiver.startBluetoothReceiver();
//startHeadsetJackListener
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.headsetPlugged))
HeadphoneJackListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.musicPlaying))
MediaPlayerListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
}
public static void stopAllReceivers()
@ -202,15 +218,18 @@ public class ReceiverCoordinator
TimeZoneListener.stopTimeZoneListener();
DateTimeListener.stopAlarmListener(AutomationService.getInstance());
NoiseListener.stopNoiseListener();
BroadcastListener.getInstance().stopListener(AutomationService.getInstance());
ProcessListener.stopProcessListener(AutomationService.getInstance());
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance());
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
try
{
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
Miscellaneous.runMethodReflective("ActivityDetectionReceiver", "stopActivityDetectionReceiver", null);
}
catch(ClassNotFoundException e)
catch(Exception e)
{
// Nothing to do, just not stopping this one.
}
@ -241,7 +260,7 @@ public class ReceiverCoordinator
// timeFrame -> too inexpensive to shutdown
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) || Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))
{
if(BatteryReceiver.haveAllPermission())
BatteryReceiver.startBatteryReceiver(AutomationService.getInstance());
@ -261,6 +280,17 @@ public class ReceiverCoordinator
NoiseListener.stopNoiseListener();
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.broadcastReceived))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting BroadcastReceiver because used in a new/changed rule.", 4);
BroadcastListener.getInstance().startListener(AutomationService.getInstance());
}
else
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down BroadcastReceiver because not used in any rule.", 4);
BroadcastListener.getInstance().stopListener(AutomationService.getInstance());
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.process_started_stopped))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting ProcessListener because used in a new/changed rule.", 4);
@ -273,7 +303,29 @@ public class ReceiverCoordinator
ProcessListener.stopProcessListener(AutomationService.getInstance());
}
if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor"))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting ScreenStateListener because used in a new/changed rule.", 4);
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
}
else
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down ScreenStateListener because not used in any rule.", 4);
ScreenStateReceiver.stopScreenStateReceiver();
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.musicPlaying))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting MediaPlayerListener because used in a new/changed rule.", 4);
MediaPlayerListener.getInstance().startListener(AutomationService.getInstance());
}
else
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down MediaPlayerListener because not used in any rule.", 4);
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
}
if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid))
{
if (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.activityDetection))
{
@ -370,6 +422,24 @@ public class ReceiverCoordinator
}
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering))
{
if(!TetheringReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "TetheringReceiver", "Starting TetheringReceiver because used in a new/changed rule.", 4);
// if(DevicePositionListener.getInstance().haveAllPermission())
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
}
}
else
{
if(TetheringReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "TetheringReceiver", "Shutting down TetheringReceiver because not used in any rule.", 4);
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
}
}
AutomationService.updateNotification();
}
}

View File

@ -12,7 +12,7 @@ import java.util.Set;
public class Settings implements SharedPreferences
{
public static final int rulesThatHaveBeenRanHistorySize = 10;
public final static int lockSoundChangesInterval = 15;
public static final int lockSoundChangesInterval = 15;
public static final int newsPollEveryXDays = 3;
public static final int newsDisplayForXDays = 3;
public static final int updateCheckFrequencyDays = 7;
@ -20,6 +20,7 @@ public class Settings implements SharedPreferences
public static final String zipFileName = "automation.zip";
public static final String constNewsOptInDone ="newsOptInDone";
public static final String constNotificationChannelCleanupApk118 ="notificationChannelCleanupApk118";
public static long minimumDistanceChangeForGpsUpdate;
public static long minimumDistanceChangeForNetworkUpdate;
@ -65,6 +66,7 @@ public class Settings implements SharedPreferences
public static boolean executeRulesAndProfilesWithSingleClick;
public static boolean displayNewsOnMainScreen;
public static boolean automaticUpdateCheck;
public static long musicCheckFrequency;
public static boolean lockSoundChanges;
public static boolean noticeAndroid9MicrophoneShown;
@ -75,57 +77,64 @@ public class Settings implements SharedPreferences
public static ArrayList<String> whatHasBeenDone;
/*
Generic settings valid for all installations and not changable
Not saved permanently.
*/
public static boolean deviceStartDone = true; // by default assume device has not just been started
public static boolean serviceStartDone = false;
/*
Generic settings valid for all installations and not changeable
*/
public static final String dateFormat = "E dd.MM.yyyy HH:mm:ss:ssss";
protected static final int default_positioningEngine = 0;
protected static final long default_minimumDistanceChangeForGpsUpdate = 100;
protected static final long default_minimumDistanceChangeForNetworkUpdate = 500; // in Meters
protected static final long default_satisfactoryAccuracyGps = 50;
protected static final long default_satisfactoryAccuracyNetwork = 1000;
protected static final int default_gpsTimeout = 300; // seconds
protected static final long default_minimumTimeBetweenUpdate = 30000; // in Milliseconds
protected static final boolean default_startServiceAtSystemBoot = false;
protected static final boolean default_writeLogFile = false;
protected static final long default_logLevel = 2;
protected static final int default_logFileMaxSize = 10;
protected static final boolean default_useTextToSpeechOnNormal = false;
protected static final boolean default_useTextToSpeechOnVibrate = false;
protected static final boolean default_useTextToSpeechOnSilent = false;
protected static final boolean default_muteTextToSpeechDuringCalls = true;
protected static final boolean default_useWifiForPositioning = true;
protected static final boolean default_useAccelerometerForPositioning = true;
protected static final long default_useAccelerometerAfterIdleTime = 5;
protected static final long default_accelerometerMovementThreshold = 2;
protected static final long default_speedMaximumTimeBetweenLocations = 4;
protected static final long default_timeBetweenNoiseLevelMeasurements = 60;
protected static final long default_lengthOfNoiseLevelMeasurements = 5;
protected static final long default_referenceValueForNoiseLevelMeasurements = 20;
protected static final boolean default_hasServiceBeenRunning = false;
protected static final boolean default_startServiceAfterAppUpdate = true;
protected static final boolean default_startNewThreadForRuleActivation = true;
protected static final boolean default_showIconWhenServiceIsRunning = true;
protected static final boolean default_httpAcceptAllCertificates = false;
protected static final int default_httpAttempts = 3;
protected static final int default_httpAttemptsTimeout = 60;
protected static final int default_httpAttemptGap = 2;
protected static final PointOfInterest default_lastActivePoi = null;
protected static final boolean default_rememberLastActivePoi = true;
protected static final int default_locationRingBufferSize=3;
protected static final long default_timeBetweenProcessMonitorings = 60;
protected static final long default_acceptDevicePositionSignalEveryX_MilliSeconds = 1000;
protected static final int default_activityDetectionFrequency = 60;
protected static final int default_activityDetectionRequiredProbability = 75;
protected static final boolean default_privacyLocationing = false;
protected static final int default_startScreen = 0;
protected static final int default_tabsPlacement = 0;
protected static final boolean default_executeRulesAndProfilesWithSingleClick = false;
protected static final boolean default_displayNewsOnMainScreen = false;
protected static final boolean default_automaticUpdateCheck = false;
protected static final boolean default_lockSoundChanges = false;
protected static final long default_lastNewsPolltime = -1;
protected static final long default_lastUpdateCheck = -1;
public static final int default_positioningEngine = 0;
public static final long default_minimumDistanceChangeForGpsUpdate = 100;
public static final long default_minimumDistanceChangeForNetworkUpdate = 500; // in Meters
public static final long default_satisfactoryAccuracyGps = 50;
public static final long default_satisfactoryAccuracyNetwork = 1000;
public static final int default_gpsTimeout = 300; // seconds
public static final long default_minimumTimeBetweenUpdate = 30000; // in Milliseconds
public static final boolean default_startServiceAtSystemBoot = false;
public static final boolean default_writeLogFile = false;
public static final long default_logLevel = 2;
public static final int default_logFileMaxSize = 10;
public static final boolean default_useTextToSpeechOnNormal = false;
public static final boolean default_useTextToSpeechOnVibrate = false;
public static final boolean default_useTextToSpeechOnSilent = false;
public static final boolean default_muteTextToSpeechDuringCalls = true;
public static final boolean default_useWifiForPositioning = true;
public static final boolean default_useAccelerometerForPositioning = true;
public static final long default_useAccelerometerAfterIdleTime = 5;
public static final long default_accelerometerMovementThreshold = 2;
public static final long default_speedMaximumTimeBetweenLocations = 4;
public static final long default_timeBetweenNoiseLevelMeasurements = 60;
public static final long default_lengthOfNoiseLevelMeasurements = 5;
public static final long default_referenceValueForNoiseLevelMeasurements = 20;
public static final boolean default_hasServiceBeenRunning = false;
public static final boolean default_startServiceAfterAppUpdate = true;
public static final boolean default_startNewThreadForRuleActivation = true;
public static final boolean default_showIconWhenServiceIsRunning = true;
public static final boolean default_httpAcceptAllCertificates = false;
public static final int default_httpAttempts = 3;
public static final int default_httpAttemptsTimeout = 60;
public static final int default_httpAttemptGap = 2;
public static final PointOfInterest default_lastActivePoi = null;
public static final boolean default_rememberLastActivePoi = true;
public static final int default_locationRingBufferSize=3;
public static final long default_timeBetweenProcessMonitorings = 60;
public static final long default_acceptDevicePositionSignalEveryX_MilliSeconds = 1000;
public static final int default_activityDetectionFrequency = 60;
public static final int default_activityDetectionRequiredProbability = 75;
public static final boolean default_privacyLocationing = false;
public static final int default_startScreen = 0;
public static final int default_tabsPlacement = 0;
public static final boolean default_executeRulesAndProfilesWithSingleClick = false;
public static final boolean default_displayNewsOnMainScreen = false;
public static final boolean default_automaticUpdateCheck = false;
public static final boolean default_lockSoundChanges = false;
public static final long default_lastNewsPolltime = -1;
public static final long default_lastUpdateCheck = -1;
public static final long default_musicCheckFrequency = 2500;
@Override
public boolean contains(String arg0)
@ -260,6 +269,11 @@ public class Settings implements SharedPreferences
startScreen = Integer.parseInt(prefs.getString("startScreen", String.valueOf(default_startScreen)));
tabsPlacement = Integer.parseInt(prefs.getString("tabsPlacement", String.valueOf(default_tabsPlacement)));
musicCheckFrequency = Long.parseLong(prefs.getString("musicCheckFrequency", String.valueOf(default_musicCheckFrequency)));
if(Settings.musicCheckFrequency == 0)
Settings.musicCheckFrequency = Settings.default_musicCheckFrequency;
executeRulesAndProfilesWithSingleClick = prefs.getBoolean("executeRulesAndProfilesWithSingleClick", default_executeRulesAndProfilesWithSingleClick);
automaticUpdateCheck = prefs.getBoolean("automaticUpdateCheck", default_automaticUpdateCheck);
displayNewsOnMainScreen = prefs.getBoolean("displayNewsOnMainScreen", default_displayNewsOnMainScreen);
@ -326,154 +340,154 @@ public class Settings implements SharedPreferences
Editor editor = prefs.edit();
if(!prefs.contains("startServiceAtSystemBoot") | force)
if(!prefs.contains("startServiceAtSystemBoot") || force)
editor.putBoolean("startServiceAtSystemBoot", default_startServiceAtSystemBoot);
if(!prefs.contains("writeLogFile") | force)
if(!prefs.contains("writeLogFile") || force)
editor.putBoolean("writeLogFile", default_writeLogFile);
// if(!prefs.contains("useTextToSpeech") | force)
// editor.putBoolean("useTextToSpeech", default_useTextToSpeech);
if(!prefs.contains("useTextToSpeechOnNormal") | force)
if(!prefs.contains("useTextToSpeechOnNormal") || force)
editor.putBoolean("useTextToSpeechOnNormal", default_useTextToSpeechOnNormal);
if(!prefs.contains("useTextToSpeechOnVibrate") | force)
if(!prefs.contains("useTextToSpeechOnVibrate") || force)
editor.putBoolean("useTextToSpeechOnVibrate", default_useTextToSpeechOnVibrate);
if(!prefs.contains("useTextToSpeechOnSilent") | force)
if(!prefs.contains("useTextToSpeechOnSilent") || force)
editor.putBoolean("useTextToSpeechOnSilent", default_useTextToSpeechOnSilent);
if(!prefs.contains("muteTextToSpeechDuringCalls") | force)
if(!prefs.contains("muteTextToSpeechDuringCalls") || force)
editor.putBoolean("muteTextToSpeechDuringCalls", default_muteTextToSpeechDuringCalls);
if(!prefs.contains("positioningEngine") | force)
if(!prefs.contains("positioningEngine") || force)
editor.putString("positioningEngine", String.valueOf(default_positioningEngine));
if(!prefs.contains("useWifiForPositioning") | force)
if(!prefs.contains("useWifiForPositioning") || force)
editor.putBoolean("useWifiForPositioning", default_useWifiForPositioning);
if(!prefs.contains("hasServiceBeenRunning") | force)
if(!prefs.contains("hasServiceBeenRunning") || force)
editor.putBoolean("hasServiceBeenRunning", default_hasServiceBeenRunning);
if(!prefs.contains("startServiceAfterAppUpdate") | force)
if(!prefs.contains("startServiceAfterAppUpdate") || force)
editor.putBoolean("startServiceAfterAppUpdate", default_startServiceAfterAppUpdate);
if(!prefs.contains("startNewThreadForRuleActivation") | force)
if(!prefs.contains("startNewThreadForRuleActivation") || force)
editor.putBoolean("startNewThreadForRuleActivation", default_startNewThreadForRuleActivation);
if(!prefs.contains("showIconWhenServiceIsRunning") | force)
if(!prefs.contains("showIconWhenServiceIsRunning") || force)
editor.putBoolean("showIconWhenServiceIsRunning", default_showIconWhenServiceIsRunning);
if(!prefs.contains("useAccelerometerForPositioning") | force)
if(!prefs.contains("useAccelerometerForPositioning") || force)
editor.putBoolean("useAccelerometerForPositioning", default_useAccelerometerForPositioning);
if(!prefs.contains("useAccelerometerAfterIdleTime") | force)
if(!prefs.contains("useAccelerometerAfterIdleTime") || force)
editor.putString("useAccelerometerAfterIdleTime", String.valueOf(default_useAccelerometerAfterIdleTime));
if(!prefs.contains("accelerometerMovementThreshold") | force)
if(!prefs.contains("accelerometerMovementThreshold") || force)
editor.putString("accelerometerMovementThreshold", String.valueOf(default_accelerometerMovementThreshold));
if(!prefs.contains("speedMaximumTimeBetweenLocations") | force)
if(!prefs.contains("speedMaximumTimeBetweenLocations") || force)
editor.putString("speedMaximumTimeBetweenLocations", String.valueOf(default_speedMaximumTimeBetweenLocations));
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE") | force)
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE") || force)
editor.putString("MINIMUM_DISTANCE_CHANGE_FOR_GPS_UPDATE", String.valueOf(default_minimumDistanceChangeForGpsUpdate));
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE") | force)
if(!prefs.contains("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE") || force)
editor.putString("MINIMUM_DISTANCE_CHANGE_FOR_NETWORK_UPDATE", String.valueOf(default_minimumDistanceChangeForNetworkUpdate));
if(!prefs.contains("SATISFACTORY_ACCURACY_GPS") | force)
if(!prefs.contains("SATISFACTORY_ACCURACY_GPS") || force)
editor.putString("SATISFACTORY_ACCURACY_GPS", String.valueOf(default_satisfactoryAccuracyGps));
if(!prefs.contains("SATISFACTORY_ACCURACY_NETWORK") | force)
if(!prefs.contains("SATISFACTORY_ACCURACY_NETWORK") || force)
editor.putString("SATISFACTORY_ACCURACY_NETWORK", String.valueOf(default_satisfactoryAccuracyNetwork));
if(!prefs.contains("gpsTimeout") | force)
if(!prefs.contains("gpsTimeout") || force)
editor.putString("gpsTimeout", String.valueOf(default_gpsTimeout));
if(!prefs.contains("MINIMUM_TIME_BETWEEN_UPDATE") | force)
if(!prefs.contains("MINIMUM_TIME_BETWEEN_UPDATE") || force)
editor.putString("MINIMUM_TIME_BETWEEN_UPDATE", String.valueOf(default_minimumTimeBetweenUpdate));
if(!prefs.contains("timeBetweenNoiseLevelMeasurements") | force)
if(!prefs.contains("timeBetweenNoiseLevelMeasurements") || force)
editor.putString("timeBetweenNoiseLevelMeasurements", String.valueOf(default_timeBetweenNoiseLevelMeasurements));
if(!prefs.contains("lengthOfNoiseLevelMeasurements") | force)
if(!prefs.contains("lengthOfNoiseLevelMeasurements") || force)
editor.putString("lengthOfNoiseLevelMeasurements", String.valueOf(default_lengthOfNoiseLevelMeasurements));
if(!prefs.contains("referenceValueForNoiseLevelMeasurements") | force)
if(!prefs.contains("referenceValueForNoiseLevelMeasurements") || force)
editor.putString("referenceValueForNoiseLevelMeasurements", String.valueOf(default_referenceValueForNoiseLevelMeasurements));
if(!prefs.contains("logLevel") | force)
if(!prefs.contains("logLevel") || force)
editor.putString("logLevel", String.valueOf(default_logLevel));
if(!prefs.contains("logFileMaxSize") | force)
if(!prefs.contains("logFileMaxSize") || force)
editor.putString("logFileMaxSize", String.valueOf(default_logFileMaxSize));
if(!prefs.contains("httpAcceptAllCertificates") | force)
if(!prefs.contains("httpAcceptAllCertificates") || force)
editor.putBoolean("httpAcceptAllCertificates", default_httpAcceptAllCertificates);
if(!prefs.contains("httpAttempts") | force)
if(!prefs.contains("httpAttempts") || force)
editor.putString("httpAttempts", String.valueOf(default_httpAttempts));
if(!prefs.contains("httpAttemptsTimeout") | force)
if(!prefs.contains("httpAttemptsTimeout") || force)
editor.putString("httpAttemptsTimeout", String.valueOf(default_httpAttemptsTimeout));
if(!prefs.contains("httpAttemptGap") | force)
if(!prefs.contains("httpAttemptGap") || force)
editor.putString("httpAttemptGap", String.valueOf(default_httpAttemptGap));
if(!prefs.contains("lastActivePoi") | force)
if(!prefs.contains("lastActivePoi") || force)
editor.putString("lastActivePoi", "null");
if(!prefs.contains("rememberLastActivePoi") | force)
if(!prefs.contains("rememberLastActivePoi") || force)
editor.putBoolean("rememberLastActivePoi", default_rememberLastActivePoi);
if(!prefs.contains("locationRingBufferSize") | force)
if(!prefs.contains("locationRingBufferSize") || force)
editor.putString("locationRingBufferSize", String.valueOf(default_locationRingBufferSize));
if(!prefs.contains("timeBetweenProcessMonitorings") | force)
if(!prefs.contains("timeBetweenProcessMonitorings") || force)
editor.putString("timeBetweenProcessMonitorings", String.valueOf(default_timeBetweenProcessMonitorings));
if(!prefs.contains("acceptDevicePositionSignalEveryX_MilliSeconds") | force)
if(!prefs.contains("acceptDevicePositionSignalEveryX_MilliSeconds") || force)
editor.putString("acceptDevicePositionSignalEveryX_MilliSeconds", String.valueOf(default_acceptDevicePositionSignalEveryX_MilliSeconds));
if(!prefs.contains("activityDetectionFrequency") | force)
if(!prefs.contains("activityDetectionFrequency") || force)
editor.putString("activityDetectionFrequency", String.valueOf(default_activityDetectionFrequency));
if(!prefs.contains("activityDetectionRequiredProbability") | force)
if(!prefs.contains("activityDetectionRequiredProbability") || force)
editor.putString("activityDetectionRequiredProbability", String.valueOf(default_activityDetectionRequiredProbability));
if(!prefs.contains("privacyLocationing") | force)
if(!prefs.contains("privacyLocationing") || force)
editor.putBoolean("privacyLocationing", default_privacyLocationing);
if(!prefs.contains("startScreen") | force)
if(!prefs.contains("startScreen") || force)
editor.putString("startScreen", String.valueOf(default_startScreen));
if(!prefs.contains("tabsPlacement") | force)
if(!prefs.contains("tabsPlacement") || force)
editor.putString("tabsPlacement", String.valueOf(default_tabsPlacement));
if(!prefs.contains("executeRulesAndProfilesWithSingleClick") | force)
if(!prefs.contains("executeRulesAndProfilesWithSingleClick") || force)
editor.putBoolean("executeRulesAndProfilesWithSingleClick", default_executeRulesAndProfilesWithSingleClick);
if(!prefs.contains("automaticUpdateCheck") | force)
if(!prefs.contains("automaticUpdateCheck") || force)
editor.putBoolean("automaticUpdateCheck", default_automaticUpdateCheck);
if(!prefs.contains("displayNewsOnMainScreen") | force)
if(!prefs.contains("displayNewsOnMainScreen") || force)
editor.putBoolean("displayNewsOnMainScreen", default_displayNewsOnMainScreen);
if(!prefs.contains("lockSoundChanges") | force)
if(!prefs.contains("musicCheckFrequency") || force)
editor.putLong("musicCheckFrequency", default_musicCheckFrequency);
if(!prefs.contains("lockSoundChanges") || force)
editor.putBoolean("lockSoundChanges", default_lockSoundChanges);
if(!prefs.contains("noticeAndroid9MicrophoneShown") | force)
if(!prefs.contains("noticeAndroid9MicrophoneShown") || force)
editor.putBoolean("noticeAndroid9MicrophoneShown", false);
if(!prefs.contains("lastNewsPolltime") | force)
if(!prefs.contains("lastNewsPolltime") || force)
editor.putLong("lastNewsPolltime", default_lastNewsPolltime);
if(!prefs.contains("lastUpdateCheck") | force)
if(!prefs.contains("lastUpdateCheck") || force)
editor.putLong("lastUpdateCheck", default_lastUpdateCheck);
if(!prefs.contains("whatHasBeenDone") | force)
if(!prefs.contains("whatHasBeenDone") || force)
editor.putString("whatHasBeenDone", "");
editor.commit();
@ -542,6 +556,10 @@ public class Settings implements SharedPreferences
editor.putBoolean("automaticUpdateCheck", automaticUpdateCheck);
editor.putBoolean("displayNewsOnMainScreen", displayNewsOnMainScreen);
if(Settings.musicCheckFrequency == 0)
Settings.musicCheckFrequency = Settings.default_musicCheckFrequency;
editor.putString("musicCheckFrequency", String.valueOf(musicCheckFrequency));
editor.putBoolean("lockSoundChanges", lockSoundChanges);
editor.putBoolean("noticeAndroid9MicrophoneShown", noticeAndroid9MicrophoneShown);
editor.putBoolean("noticeAndroid10WifiShown", noticeAndroid10WifiShown);
@ -588,5 +606,4 @@ public class Settings implements SharedPreferences
// TODO Auto-generated method stub
return null;
}
}

View File

@ -6,8 +6,8 @@ import java.util.ArrayList;
public class TimeFrame
{
// Defines a timeframe
protected Time triggerTimeStart;
protected Time triggerTimeStop;
protected TimeObject triggerTimeStart;
protected TimeObject triggerTimeStop;
protected long repetition;
protected final static String separator = "/";
@ -34,20 +34,20 @@ public class TimeFrame
}
}
public Time getTriggerTimeStart()
public TimeObject getTriggerTimeStart()
{
return triggerTimeStart;
}
public void setTriggerTimeStart(Time triggerTimeStart)
public void setTriggerTimeStart(TimeObject triggerTimeStart)
{
this.triggerTimeStart = triggerTimeStart;
}
public Time getTriggerTimeStop()
public TimeObject getTriggerTimeStop()
{
return triggerTimeStop;
}
public void setTriggerTimeStop(Time triggerTimeStop)
public void setTriggerTimeStop(TimeObject triggerTimeStop)
{
this.triggerTimeStop = triggerTimeStop;
}
@ -62,7 +62,7 @@ public class TimeFrame
this.repetition = repetition;
}
public TimeFrame (Time timeStart, Time timeEnd, ArrayList<Integer> dayList2, long repetition)
public TimeFrame (TimeObject timeStart, TimeObject timeEnd, ArrayList<Integer> dayList2, long repetition)
{
this.setTriggerTimeStart(timeStart);
this.setTriggerTimeStop(timeEnd);
@ -73,13 +73,36 @@ public class TimeFrame
public TimeFrame (String fileContent)
{
String[] dateArray = fileContent.split(separator); // example: timestart/timestop/days[int]/repetition
this.setTriggerTimeStart(Time.valueOf(dateArray[0]));
this.setTriggerTimeStop(Time.valueOf(dateArray[1]));
this.setTriggerTimeStart(TimeObject.valueOf(dateArray[0]));
this.setTriggerTimeStop(TimeObject.valueOf(dateArray[1]));
this.setDayListFromString(dateArray[2]);
if(dateArray.length > 3) // may not exist in old config files
this.setRepetition(Long.parseLong(dateArray[3]));
}
public String toTriggerParameter2String()
{
StringBuilder response = new StringBuilder();
response.append(this.getTriggerTimeStart().getHours() + ":" + this.getTriggerTimeStart().getMinutes() + ":0");
response.append(separator);
response.append(this.getTriggerTimeStop().getHours() + ":" + this.getTriggerTimeStop().getMinutes() + ":0");
response.append(separator);
StringBuilder days = new StringBuilder();
for(int day : dayList)
days.append(String.valueOf(day));
response.append(days.toString());
if(this.repetition > 0)
{
response.append(separator + this.getRepetition());
}
return response.toString();
}
@Override
public String toString()
{

View File

@ -0,0 +1,68 @@
package com.jens.automation2;
import java.sql.Time;
public class TimeObject
{
int hours, minutes, seconds;
public TimeObject()
{
}
public int getHours()
{
return hours;
}
public void setHours(int hours)
{
this.hours = hours;
}
public int getMinutes()
{
return minutes;
}
public void setMinutes(int minutes)
{
this.minutes = minutes;
}
public int getSeconds()
{
return seconds;
}
public void setSeconds(int seconds)
{
this.seconds = seconds;
}
public TimeObject(int hours, int minutes, int seconds)
{
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
public static TimeObject valueOf(String input)
{
TimeObject ro = null;
if(input.contains(":"))
{
String[] parts = input.split(":");
if(parts.length == 2)
ro = new TimeObject(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), 0);
else if(parts.length == 3)
ro = new TimeObject(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
else
Miscellaneous.logEvent("w", "TimeObject", "Invalid length for time. Input: " + input, 4);
}
return ro;
}
}

View File

@ -3,7 +3,6 @@ package com.jens.automation2;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
import android.util.Log;
@ -14,29 +13,120 @@ import com.jens.automation2.location.LocationProvider;
import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.BatteryReceiver;
import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener;
import com.jens.automation2.receivers.MediaPlayerListener;
import com.jens.automation2.receivers.NfcReceiver;
import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.NotificationListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT;
import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
import org.apache.commons.lang3.StringUtils;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class Trigger
{
public enum Trigger_Enum
{
pointOfInterest,
timeFrame,
charging,
batteryLevel,
usb_host_connection,
speed,
noiseLevel,
wifiConnection,
process_started_stopped,
airplaneMode,
roaming,
nfcTag,
activityDetection,
bluetoothConnection,
headsetPlugged,
notification,
deviceOrientation,
profileActive,
screenState,
musicPlaying,
deviceStarts,
serviceStarts,
broadcastReceived,
tethering,
phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
switch(this)
{
case pointOfInterest:
return context.getResources().getString(R.string.triggerPointOfInterest);
case timeFrame:
return context.getResources().getString(R.string.triggerTimeFrame);
case charging:
return context.getResources().getString(R.string.triggerCharging);
case batteryLevel:
return context.getResources().getString(R.string.batteryLevel);
case usb_host_connection:
return context.getResources().getString(R.string.triggerUsb_host_connection);
case speed:
return context.getResources().getString(R.string.triggerSpeed);
case noiseLevel:
return context.getResources().getString(R.string.triggerNoiseLevel);
case wifiConnection:
return context.getResources().getString(R.string.wifiConnection);
case process_started_stopped:
return context.getResources().getString(R.string.anotherAppIsRunning);
case airplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case roaming:
return context.getResources().getString(R.string.roaming);
case phoneCall:
return context.getResources().getString(R.string.phoneCall);
case nfcTag:
return context.getResources().getString(R.string.nfcTag);
case activityDetection:
return context.getResources().getString(R.string.activityDetection);
case bluetoothConnection:
return context.getResources().getString(R.string.bluetoothConnection);
case headsetPlugged:
return context.getResources().getString(R.string.triggerHeadsetPlugged);
case notification:
return context.getResources().getString(R.string.notification);
case deviceOrientation:
return context.getResources().getString(R.string.deviceOrientation);
case profileActive:
return context.getResources().getString(R.string.profile);
case musicPlaying:
return context.getResources().getString(R.string.musicPlaying);
case screenState:
return context.getResources().getString(R.string.screenState);
case deviceStarts:
return context.getResources().getString(R.string.deviceStarts);
case serviceStarts:
return context.getResources().getString(R.string.serviceStarts);
case broadcastReceived:
return context.getResources().getString(R.string.broadcastReceivedTitle);
case tethering:
return context.getResources().getString(R.string.tetheringState);
default:
return "Unknown";
}
}
};
Rule parentRule = null;
Calendar lastTimeNotApplied = null;
final static String anyAppString = "-1";
public boolean applies(Object triggeringObject, Context context)
{
boolean result = true;
@ -121,6 +211,30 @@ public class Trigger
if(!checkProfileActive())
result = false;
break;
case musicPlaying:
if(!checkMusicPlaying())
result = false;
break;
case screenState:
if(!checkScreenState())
result = false;
break;
case deviceStarts:
if(!checkDeviceStarts())
result = false;
break;
case serviceStarts:
if(!checkServiceStarts())
result = false;
break;
case broadcastReceived:
if(!checkBroadcastReceived())
result = false;
break;
case tethering:
if(!checkTetheringActive())
result = false;
break;
default:
break;
}
@ -137,6 +251,18 @@ public class Trigger
return result;
}
boolean checkBroadcastReceived()
{
/*
We cannot reasonably check the current state for every broadcast event.
We can only hope that when starting the receiver we get an initial broadcast
for every current state. That collection of states will be saved and checked if
it contains the specific event of this trigger.
*/
return triggerParameter == BroadcastListener.getInstance().hasBroadcastOccurred(triggerParameter2);
}
boolean checkNotification()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
@ -163,15 +289,13 @@ public class Trigger
{
if(getParentRule().getLastExecution() == null || sbn.getPostTime() > this.getParentRule().getLastExecution().getTimeInMillis())
{
String notificationApp = sbn.getPackageName();
String notificationTitle = null;
String notificationText = null;
NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn);
Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5);
Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().getName() + ": " + sn.toString(), 5);
if (!myApp.equals("-1"))
if (!myApp.equals(anyAppString))
{
if (!notificationApp.equalsIgnoreCase(myApp))
if (!myApp.equalsIgnoreCase(sn.getApp()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5);
continue;
@ -179,6 +303,9 @@ public class Trigger
}
else
{
/*
Notifications from Automation are disregarded to avoid infinite loops.
*/
if(myApp.equals(BuildConfig.APPLICATION_ID))
{
return false;
@ -190,15 +317,10 @@ public class Trigger
https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications
*/
Bundle extras = sbn.getNotification().extras;
// T I T L E
if (extras.containsKey(EXTRA_TITLE))
notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE);
if (!StringUtils.isEmpty(requiredTitle))
{
if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle))
if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5);
continue;
@ -208,13 +330,9 @@ public class Trigger
Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5);
// T E X T
if (extras.containsKey(EXTRA_TEXT))
notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT);
if (!StringUtils.isEmpty(requiredText))
{
if (!Miscellaneous.compare(myTextDir, requiredText, notificationText))
if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText()))
{
Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5);
continue;
@ -243,7 +361,7 @@ public class Trigger
String title = NotificationListener.getLastNotification().getTitle();
String text = NotificationListener.getLastNotification().getText();
if (!myApp.equals("-1"))
if (!myApp.equals(anyAppString))
{
if (!app.equalsIgnoreCase(myApp))
return false;
@ -277,6 +395,21 @@ public class Trigger
return true;
}
boolean checkMusicPlaying()
{
return triggerParameter == MediaPlayerListener.isAudioPlaying(Miscellaneous.getAnyContext());
}
boolean checkDeviceStarts()
{
return checkServiceStarts() && !Settings.deviceStartDone;
}
boolean checkServiceStarts()
{
return !Settings.serviceStartDone;
}
boolean checkProfileActive()
{
String demandedProfileName = getTriggerParameter2().split(Trigger.triggerParameter2Split)[0];
@ -314,6 +447,25 @@ public class Trigger
return false;
}
boolean checkScreenState()
{
try
{
int desiredState = Integer.parseInt(getTriggerParameter2());
if(desiredState == ScreenStateReceiver.SCREEN_STATE_OFF || desiredState == ScreenStateReceiver.SCREEN_STATE_ON)
return desiredState == ScreenStateReceiver.getScreenPowerState();
else
return desiredState == ScreenStateReceiver.getScreenLockState();
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Trigger", "Error checking screen state trigger.", 4);
}
return false;
}
boolean checkDeviceOrientation()
{
String deviceOrientationPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
@ -538,7 +690,19 @@ public class Trigger
boolean checkProcess()
{
boolean running = ProcessListener.getRunningApps().contains(this.getProcessName());
boolean running = false;
if(getTriggerParameter2().contains(triggerParameter2Split))
{
String parts[] = triggerParameter2.split(triggerParameter2Split);
for(String appName : ProcessListener.getRunningApps())
{
if(appName.startsWith(parts[0]))
running = true;
}
}
else
running = ProcessListener.getRunningApps().contains(this.getProcessName());
if(running)
Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is currently running.", 4);
@ -762,6 +926,11 @@ public class Trigger
return true;
}
boolean checkTetheringActive()
{
return TetheringReceiver.isTetheringActive() == triggerParameter;
}
public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution)
{
/*
@ -777,7 +946,7 @@ public class Trigger
triggeringTime = new Date();
String timeString = String.valueOf(triggeringTime.getHours()) + ":" + String.valueOf(triggeringTime.getMinutes()) + ":" + String.valueOf(triggeringTime.getSeconds());
Time nowTime = Time.valueOf(timeString);
TimeObject nowTime = TimeObject.valueOf(timeString);
Calendar calNow = Calendar.getInstance();
try
@ -793,16 +962,20 @@ public class Trigger
&&
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0
)
|
||
// Other case, start time higher than end time, timeframe goes over midnight
(
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) < 0
&&
(Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
|
||
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0)
)
||
// further case: start and end times are identical, meaning a 24h window
(
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) == 0
)
)
{
// We are in the timeframe
@ -928,7 +1101,7 @@ public class Trigger
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
{
Calendar calSet;
Time setTime;
TimeObject setTime;
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
if(tf.getRepetition() > 0)
@ -944,8 +1117,6 @@ public class Trigger
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
// if(this.applies(null))
// {
// If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1);
@ -956,15 +1127,7 @@ public class Trigger
Calendar calSchedule = Calendar.getInstance();
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
/*
* Das war mal aktiviert. Allerdings: Die ganze Funktion liefert zurück, wenn die Regel NOCH nicht
* zutrifft, aber wir z.B. gleich den zeitlichen Bereich betreten.
*/
// if(trigger.checkDateTime(calSchedule.getTime(), false))
// {
return calSchedule;
// }
// }
}
else
Miscellaneous.logEvent("i", "Trigger", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
@ -997,73 +1160,14 @@ public class Trigger
return false;
}
/*
* Can be several things:
* -PointOfInterest
* -TimeFrame
* -Event (like charging, cable plugged, etc.)
*/
public enum Trigger_Enum {
pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, deviceOrientation, profileActive, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
switch(this)
{
case pointOfInterest:
return context.getResources().getString(R.string.triggerPointOfInterest);
case timeFrame:
return context.getResources().getString(R.string.triggerTimeFrame);
case charging:
return context.getResources().getString(R.string.triggerCharging);
case batteryLevel:
return context.getResources().getString(R.string.batteryLevel);
case usb_host_connection:
return context.getResources().getString(R.string.triggerUsb_host_connection);
case speed:
return context.getResources().getString(R.string.triggerSpeed);
case noiseLevel:
return context.getResources().getString(R.string.triggerNoiseLevel);
case wifiConnection:
return context.getResources().getString(R.string.wifiConnection);
case process_started_stopped:
return context.getResources().getString(R.string.anotherAppIsRunning);
case airplaneMode:
return context.getResources().getString(R.string.airplaneMode);
case roaming:
return context.getResources().getString(R.string.roaming);
case phoneCall:
return context.getResources().getString(R.string.phoneCall);
case nfcTag:
return context.getResources().getString(R.string.nfcTag);
case activityDetection:
return context.getResources().getString(R.string.activityDetection);
case bluetoothConnection:
return context.getResources().getString(R.string.bluetoothConnection);
case headsetPlugged:
return context.getResources().getString(R.string.triggerHeadsetPlugged);
case notification:
return context.getResources().getString(R.string.notification);
case deviceOrientation:
return context.getResources().getString(R.string.deviceOrientation);
case profileActive:
return context.getResources().getString(R.string.profile);
default:
return "Unknown";
}
}
};
private boolean triggerParameter; //if true->started event, if false->stopped
private String triggerParameter2;
boolean triggerParameter; //if true->started event, if false->stopped
String triggerParameter2;
public static final String triggerParameter2Split = "tp2split";
private Trigger_Enum triggerType = null;
private PointOfInterest pointOfInterest = null;
private TimeFrame timeFrame;
Trigger_Enum triggerType = null;
PointOfInterest pointOfInterest = null;
TimeFrame timeFrame;
public static String triggerPhoneCallStateRinging = "ringing";
public static String triggerPhoneCallStateStarted = "started";
@ -1073,17 +1177,17 @@ public class Trigger
public static String triggerPhoneCallDirectionAny = "any";
public static String triggerPhoneCallNumberAny = "any";
private double speed; //km/h
private long noiseLevelDb;
private String processName = null;
private int batteryLevel;
private int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
private String phoneNumber = null;
private String nfcTagId = null;
private String bluetoothEvent = null;
private String bluetoothDeviceAddress = null;
private int activityDetectionType = -1;
private int headphoneType = -1;
double speed; //km/h
long noiseLevelDb;
String processName = null;
int batteryLevel;
int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
String phoneNumber = null;
String nfcTagId = null;
String bluetoothEvent = null;
String bluetoothDeviceAddress = null;
int activityDetectionType = -1;
int headphoneType = -1;
public int getHeadphoneType()
{
@ -1191,9 +1295,9 @@ public class Trigger
return triggerType;
}
public void setTriggerType(Trigger_Enum settriggerType)
public void setTriggerType(Trigger_Enum setTriggerType)
{
this.triggerType = settriggerType;
this.triggerType = setTriggerType;
}
public boolean getTriggerParameter()
@ -1466,7 +1570,7 @@ public class Trigger
StringBuilder triggerBuilder = new StringBuilder();
String appString;
if (app.equalsIgnoreCase("-1"))
if (app.equalsIgnoreCase(anyAppString))
appString = Miscellaneous.getAnyContext().getResources().getString(R.string.anyApp);
else
appString = "app " + app;
@ -1486,7 +1590,7 @@ public class Trigger
}
else
{
setTriggerParameter2("-1" + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split);
setTriggerParameter2(anyAppString + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split + directionEquals + triggerParameter2Split + triggerParameter2Split);
}
break;
case deviceOrientation:
@ -1498,6 +1602,58 @@ public class Trigger
else
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.profileNotActive), getTriggerParameter2().split(Trigger.triggerParameter2Split)[0]));
break;
case musicPlaying:
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getString(R.string.musicIsPlaying));
else
returnString.append(Miscellaneous.getAnyContext().getString(R.string.musicIsNotPlaying));
break;
case screenState:
String state;
switch(triggerParameter2)
{
case "0":
state = Miscellaneous.getAnyContext().getString(R.string.off);
break;
case "1":
state = Miscellaneous.getAnyContext().getString(R.string.on);
break;
case "2":
state = Miscellaneous.getAnyContext().getString(R.string.unlocked);
break;
case "3":
state = Miscellaneous.getAnyContext().getString(R.string.lockedWithoutSecurity);
break;
case "4":
state = Miscellaneous.getAnyContext().getString(R.string.lockedWithSecurity);
break;
default:
state = Miscellaneous.getAnyContext().getString(R.string.unknown);
}
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.screenIs), state));
break;
case deviceStarts:
// This type doesn't have an activate/deactivate equivalent
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.deviceHasJustStarted));
break;
case serviceStarts:
// This type doesn't have an activate/deactivate equivalent
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.serviceHasJustStarted));
break;
case broadcastReceived:
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.broadcastReceived));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.broadcastNotReceived));
returnString.append(": " + triggerParameter2);
break;
case tethering:
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringActive));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringNotActive));
break;
default:
returnString.append("error");
break;
@ -1508,6 +1664,7 @@ public class Trigger
public static final String directionEquals = "eq";
public static final String directionContains = "ct";
public static final String directionNotContains = "nc";
public static final String directionStartsWith = "sw";
public static final String directionEndsWith = "ew";
public static final String directionNotEquals = "ne";
@ -1520,6 +1677,8 @@ public class Trigger
return Miscellaneous.getAnyContext().getString(R.string.directionStringEquals);
case directionContains:
return Miscellaneous.getAnyContext().getString(R.string.directionStringContains);
case directionNotContains:
return Miscellaneous.getAnyContext().getString(R.string.directionStringDoesNotContain);
case directionStartsWith:
return Miscellaneous.getAnyContext().getString(R.string.directionStringStartsWith);
case directionEndsWith:
@ -1537,6 +1696,8 @@ public class Trigger
return directionEquals;
else if(direction.equalsIgnoreCase(Miscellaneous.getAnyContext().getString(R.string.directionStringContains)))
return directionContains;
else if(direction.equalsIgnoreCase(Miscellaneous.getAnyContext().getString(R.string.directionStringDoesNotContain)))
return directionNotContains;
else if(direction.equalsIgnoreCase(Miscellaneous.getAnyContext().getString(R.string.directionStringStartsWith)))
return directionStartsWith;
else if(direction.equalsIgnoreCase(Miscellaneous.getAnyContext().getString(R.string.directionStringEndsWith)))
@ -1551,10 +1712,6 @@ public class Trigger
{
ArrayList<String> triggerTypesList = new ArrayList<String>();
/*for(int i=0; i<Trigger_Enum.values().length; i++)
{
triggerTypesList.add(Trigger_Enum.values()[i].toString());
}*/
for(Trigger_Enum triggerType : Trigger_Enum.values())
triggerTypesList.add(triggerType.name());
@ -1566,10 +1723,6 @@ public class Trigger
{
ArrayList<String> triggerTypesList = new ArrayList<String>();
/*for(int i=0; i<Trigger_Enum.values().length; i++)
{
triggerTypesList.add(Trigger_Enum.values()[i].getFullName(context));
}*/
for(Trigger_Enum triggerType : Trigger_Enum.values())
triggerTypesList.add(triggerType.getFullName(context));

View File

@ -254,8 +254,6 @@ public class XmlFileInterface
else
serializer.text("null");
}
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.timeFrame)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTimeFrame().toString());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.speed)
serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getSpeed()));
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.noiseLevel)
@ -263,11 +261,9 @@ public class XmlFileInterface
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.wifiConnection)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerParameter2());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.process_started_stopped)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getProcessName());
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerParameter2());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.batteryLevel)
serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getBatteryLevel()));
// else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.phoneCall)
// serializer.text(String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getPhoneDirection()) + "," + String.valueOf(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getPhoneNumber()));
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.nfcTag)
serializer.text(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getNfcTagId());
else if(Rule.getRuleCollection().get(i).getTriggerSet().get(j).getTriggerType() == Trigger_Enum.activityDetection)
@ -840,7 +836,6 @@ public class XmlFileInterface
private static Trigger readTrigger(XmlPullParser parser) throws IOException, XmlPullParserException
{
/* FILE EXAMPE:
* *****************
* <Automation>
@ -943,8 +938,16 @@ public class XmlFileInterface
}
else if(newTrigger.getTriggerType() == Trigger_Enum.process_started_stopped)
{
newTrigger.setProcessName(triggerParameter2);
newTrigger.setTriggerParameter2(triggerParameter2);
if(triggerParameter2.contains(triggerParameter2Split))
{
String[] parts = triggerParameter2.split(triggerParameter2Split);
newTrigger.setProcessName(parts[1]);
}
else
newTrigger.setProcessName(triggerParameter2);
}
else if(newTrigger.getTriggerType() == Trigger_Enum.phoneCall)
{
@ -1154,12 +1157,17 @@ public class XmlFileInterface
newAction.setAction(Action_Enum.disableScreenRotation);
else if(actionNameString.equals("disableScreenRotation"))
newAction.setAction(Action_Enum.disableScreenRotation);
else if(actionNameString.equals("playMusic"))
{
newAction.setAction(Action_Enum.controlMediaPlayback);
newAction.setParameter2("1");
}
else if(actionNameString.equals("wakeupDevice"))
{
newAction.setAction(Action_Enum.turnScreenOnOrOff);
newAction.setParameter1(true);
}
// *** deprecated
// *** :deprecated
else
newAction.setAction(Action_Enum.valueOf(actionNameString));
@ -1273,14 +1281,14 @@ public class XmlFileInterface
{
String newTag;
if(tag.contains(Action.intentPairSeperator)) // already has new format
if(tag.contains(Action.intentPairSeparator)) // already has new format
newTag = tag;
else
newTag = tag.replace("/", Action.intentPairSeperator);
newTag = tag.replace("/", Action.intentPairSeparator);
String[] newTagPieces = newTag.split(";");
if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeperator)))
if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeparator)))
{
newTag = Actions.dummyPackageString + ";" + newTag;
newTagPieces = newTag.split(";");
@ -1290,7 +1298,7 @@ public class XmlFileInterface
newTag += ";" + ActivityManageActionStartActivity.startByActivityString;
else if(newTagPieces.length >= 3)
{
if(newTagPieces[2].contains(Action.intentPairSeperator))
if(newTagPieces[2].contains(Action.intentPairSeparator))
newTag = newTagPieces[0] + ";" + newTagPieces[1] + ";" + ActivityManageActionStartActivity.startByActivityString + ";" + newTagPieces[2];
}

View File

@ -189,7 +189,7 @@ public class LocationProvider
/*
Due to strange factors the time difference might be 0 resulting in mathematical error.
*/
if (Double.isInfinite(currentSpeed) | Double.isNaN(currentSpeed))
if (Double.isInfinite(currentSpeed) || Double.isNaN(currentSpeed))
Miscellaneous.logEvent("i", "Speed", "Error while calculating speed.", 4);
else
{
@ -232,12 +232,6 @@ public class LocationProvider
public void startLocationService()
{
// if(Settings.useAccelerometerForPositioning && !Miscellaneous.isAndroidEmulator())
// {
// accelerometerHandler = new AccelerometerHandler();
// mySensorActivity = new SensorActivity(this);
// }
// startPhoneStateListener
PhoneStatusListener.startPhoneStatusListener(parentService); // also used to mute anouncements during calls
@ -246,10 +240,8 @@ public class LocationProvider
if(Settings.positioningEngine == 0)
{
if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed))
if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) || Rule.isAnyRuleUsing(Trigger_Enum.speed))
{
// TelephonyManager telephonyManager = (TelephonyManager) AutomationService.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
// startCellLocationChangedReceiver
if (CellLocationChangedReceiver.isCellLocationChangedReceiverPossible())
{
@ -432,7 +424,7 @@ public class LocationProvider
}
// *********** RULE CHANGES ***********
if(!CellLocationChangedReceiver.isCellLocationListenerActive() && (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger_Enum.speed)))
if(!CellLocationChangedReceiver.isCellLocationListenerActive() && (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest) || Rule.isAnyRuleUsing(Trigger_Enum.speed)))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting NoiseListener CellLocationChangedReceiver because used in a new/changed rule.", 4);
if(CellLocationChangedReceiver.haveAllPermission())
@ -514,7 +506,6 @@ public class LocationProvider
Message msg = new Message();
msg.what = 1;
speedHandler.sendMessageAtTime(msg, timeOfForcedLocationCheck.getTimeInMillis());
// speedHandler.sendMessageDelayed(msg, delayTime);
speedTimerActive = true;
}
else
@ -531,7 +522,7 @@ public class LocationProvider
if(msg.what == 1)
{
// time is up, no cell location updates since x minutes, start accelerometer
String text = "Timer triggered. Based on the last location and speed we may be at a POI. Forcing location update in case CellLocationChangedReceiver didn\'t fire.";
Miscellaneous.logEvent("i", "LocationProvider", "Timer triggered. Based on the last location and speed we may be at a POI. Forcing location update in case CellLocationChangedReceiver didn\'t fire.", 5);
Location currentLocation = CellLocationChangedReceiver.getInstance().getLocation("coarse");
AutomationService.getInstance().getLocationProvider().setCurrentLocation(currentLocation, false);

View File

@ -26,7 +26,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
public static Boolean wasConnected = false;
protected static String lastWifiSsid = "";
public static boolean lastConnectedState = false;
protected static boolean mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = true;
protected static boolean mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true;
protected static WifiBroadcastReceiver wifiBrInstance;
protected static IntentFilter wifiListenerIntentFilter;
protected static boolean wifiListenerActive=false;
@ -41,6 +41,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
if(newWifiSsid.startsWith("\"") && newWifiSsid.endsWith("\""))
newWifiSsid = newWifiSsid.substring(1, newWifiSsid.length()-1);
if(newWifiSsid.length() > 0)
WifiBroadcastReceiver.lastWifiSsid = newWifiSsid;
}
@ -51,7 +52,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
public static boolean mayCellLocationReceiverBeActivated()
{
return mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi;
return mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView;
}
@Override
@ -62,11 +63,6 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
// int state = -1;
NetworkInfo myWifi = null;
// if(intent.getAction().equals(WifiManager.RSSI_CHANGED_ACTION)) //gefeuert bei Verbindung
// {
// Miscellaneous.logEvent("i", "WifiReceiver", "RSSI_CHANGED_ACTION: " + String.valueOf(intent.getIntExtra(WifiManager.RSSI_CHANGED_ACTION, -1)));
// }
// else
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) //gefeuert bei Trennung
{
// state = intent.getIntExtra(WifiManager.NETWORK_STATE_CHANGED_ACTION, -1);
@ -74,7 +70,6 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
myWifi = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
}
WifiManager myWifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
// ConnectivityManager connManager = (ConnectivityManager)context.getSystemService(context.CONNECTIVITY_SERVICE);
// myWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
@ -94,8 +89,14 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
if(Settings.useWifiForPositioning && PointOfInterest.reachedPoiWithActivateWifiRule()) // Poi has wifi
{
Miscellaneous.logEvent("i", "WifiReceiver", context.getResources().getString(R.string.poiHasWifiStoppingCellLocationListener), 2);
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = false;
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = false;
CellLocationChangedReceiver.stopCellLocationChangedReceiver();
/*
TODO: Every time the screen is turned on, we receiver a "wifi has been connected"-event.
This is technically wrong and not really any changed to when the screen was off. It has
to be filtered.
*/
}
else
{
@ -109,7 +110,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
{
wasConnected = true;
Miscellaneous.logEvent("i", "WifiReceiver", "WifiReceiver just activated. Wifi already connected. Stopping CellLocationReceiver", 3);
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = false;
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = false;
CellLocationChangedReceiver.stopCellLocationChangedReceiver();
SensorActivity.stopAccelerometerTimer();
String ssid = myWifiManager.getConnectionInfo().getSSID();
@ -125,7 +126,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
{
wasConnected = false;
Miscellaneous.logEvent("i", "WifiReceiver", String.format(context.getResources().getString(R.string.disconnectedFromWifi), getLastWifiSsid()) + " Switching to CellLocationChangedReceiver.", 3);
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = true;
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true;
CellLocationChangedReceiver.startCellLocationChangedReceiver();
lastConnectedState = false;
findRules(AutomationService.getInstance());

View File

@ -99,15 +99,12 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW))
{
Log.i("Battery", "Low battery event");
Miscellaneous.logEvent("i", "Battery", "Low battery event", 5);
}
else
{
try
{
// Miscellaneous.logEvent("i", "BatteryReceiver", "Received battery event.");
// if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED))
// {
batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
// int scale = -1;
// int voltage = -1;
@ -120,13 +117,13 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int statusPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
// Miscellaneous.logEvent("i", "BatteryReceiver", "Status: " + String.valueOf(statusPlugged));
Miscellaneous.logEvent("i", "BatteryReceiver", "Status: " + String.valueOf(statusPlugged), 5);
switch(statusPlugged)
{
case BatteryManager.BATTERY_PLUGGED_AC:
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
// Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.");
Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.", 5);
this.actionCharging(context);
break;
case BatteryManager.BATTERY_PLUGGED_USB:
@ -136,11 +133,8 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
switch(status)
{
// case BatteryManager.BATTERY_STATUS_CHARGING:
// break;
case BatteryManager.BATTERY_STATUS_FULL:
// Toast.makeText(context, "Regular charging full", Toast.LENGTH_LONG).show();
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.");
Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.", 5);
this.actionCharging(context);
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
@ -264,11 +258,13 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
}
}
}
@Override
public void startListener(AutomationService automationService)
{
BatteryReceiver.startBatteryReceiver(automationService);
}
@Override
public void stopListener(AutomationService automationService)
{

View File

@ -0,0 +1,168 @@
package com.jens.automation2.receivers;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class BroadcastListener extends android.content.BroadcastReceiver implements AutomationListenerInterface
{
ArrayList<EventOccurrence> broadcastsCollection = new ArrayList<>();
public static AutomationService automationServiceRef = null;
private static boolean broadcastReceiverActive = false;
private static BroadcastListener broadcastReceiverInstance = null;
private static IntentFilter broadcastIntentFilter = null;
private static Intent broadcastStatus = null;
public static BroadcastListener getInstance()
{
if(broadcastReceiverInstance == null)
broadcastReceiverInstance = new BroadcastListener();
return broadcastReceiverInstance;
}
public static class EventOccurrence
{
Calendar time;
String event;
public EventOccurrence(Calendar time, String event)
{
this.time = time;
this.event = event;
}
}
@Override
public void onReceive(Context context, Intent intent)
{
broadcastsCollection.add(new EventOccurrence(Calendar.getInstance(), intent.getAction()));
for(String key : intent.getExtras().keySet())
{
Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.broadcastReceived);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
public ArrayList<EventOccurrence> getBroadcastsCollection()
{
return broadcastsCollection;
}
public boolean hasBroadcastOccurred(String event)
{
for(EventOccurrence eo : broadcastsCollection)
{
if(eo.event.equalsIgnoreCase(event))
return true;
}
return false;
}
public boolean hasBroadcastOccurredSince(String event, Calendar timeLimit)
{
for(EventOccurrence eo : broadcastsCollection)
{
if(eo.event.equalsIgnoreCase(event) && (timeLimit == null || eo.time.getTimeInMillis() > timeLimit.getTimeInMillis()))
return true;
}
return false;
}
@Override
public void startListener(AutomationService automationService)
{
if(!broadcastReceiverActive)
{
BroadcastListener.automationServiceRef = automationService;
if(broadcastReceiverInstance == null)
broadcastReceiverInstance = new BroadcastListener();
if(broadcastIntentFilter == null)
{
broadcastIntentFilter = new IntentFilter();
List<String> actionList = new ArrayList<>();
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.broadcastReceived);
for(int i=0; i<ruleCandidates.size(); i++)
{
for(Trigger t : ruleCandidates.get(i).getTriggerSet())
{
if(t.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
ActivityPermissions.addToArrayListUnique(t.getTriggerParameter2(), actionList);
}
}
}
for(String s : actionList)
broadcastIntentFilter.addAction(s);
}
try
{
broadcastStatus = automationServiceRef.registerReceiver(broadcastReceiverInstance, broadcastIntentFilter);
broadcastReceiverActive = true;
}
catch(Exception e)
{
/*
We might be confronted with permission issues here.
*/
Miscellaneous.logEvent("e", "BroadcastListener", Log.getStackTraceString(e), 1);
broadcastReceiverActive = false;
}
}
}
@Override
public void stopListener(AutomationService automationService)
{
if(broadcastReceiverActive)
{
if(broadcastReceiverInstance != null)
{
automationServiceRef.unregisterReceiver(broadcastReceiverInstance);
broadcastReceiverInstance = null;
}
broadcastReceiverActive = false;
}
}
@Override
public boolean isListenerRunning()
{
return broadcastReceiverActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[] { Trigger.Trigger_Enum.broadcastReceived };
}
}

View File

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

View File

@ -34,17 +34,18 @@ public class DeviceOrientationListener implements SensorEventListener, Automatio
static int sensorValueCounter = 0;
// Gravity rotational data
private float gravity[];
float gravity[];
// Magnetic rotational data
private float magnetic[]; //for magnetic rotational data
private float accels[] = new float[3];
private float mags[] = new float[3];
private float[] values = new float[3];
float magnetic[]; //for magnetic rotational data
float accels[] = new float[3];
float mags[] = new float[3];
float[] values = new float[3];
boolean hasMagneticSensor=false;
// azimuth, pitch and roll
private float azimuth;
private float pitch;
private float roll;
float azimuth;
float pitch;
float roll;
boolean applies = false;
boolean flipped = false;
@ -91,7 +92,7 @@ public class DeviceOrientationListener implements SensorEventListener, Automatio
isRunning = true;
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
hasMagneticSensor = sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
}
}
@ -129,6 +130,9 @@ public class DeviceOrientationListener implements SensorEventListener, Automatio
break;
}
if (!hasMagneticSensor)
mags=new float[]{1f,1f,1f};
if (mags != null && accels != null)
{
gravity = new float[9];

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,274 @@
package com.jens.automation2.receivers;
import android.Manifest;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.provider.Settings;
import androidx.annotation.RequiresApi;
import com.jens.automation2.Actions;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class ScreenStateReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
static int screenPowerState = -1; // initialize with a better value than this
static int screenLockState = -1; // initialize with a better value than this
public static AutomationService automationServiceRef = null;
private static boolean screenStateReceiverActive = false;
private static IntentFilter screenStateIntentFilter = null;
private static Intent screenStatusIntent = null;
private static BroadcastReceiver screenStateReceiverInstance = null;
public final static String broadcastScreenLockedWithoutSecurity = "automation.system.screen_locked_without_security";
public final static String broadcastScreenLockedWithSecurity = "automation.system.screen_locked_with_security";
public final static int SCREEN_STATE_OFF = 0;
public final static int SCREEN_STATE_ON = 1;
public final static int SCREEN_STATE_UNLOCKED = 2;
public final static int SCREEN_STATE_LOCKED_WITHOUT_SECURITY = 3;
public final static int SCREEN_STATE_LOCKED_WITH_SECURITY = 4;
public static BroadcastReceiver getScreenStateReceiverInstance()
{
if (screenStateReceiverInstance == null)
screenStateReceiverInstance = new ScreenStateReceiver();
return screenStateReceiverInstance;
}
public static void startScreenStateReceiver(final AutomationService automationServiceRef)
{
if (!screenStateReceiverActive)
{
ScreenStateReceiver.automationServiceRef = automationServiceRef;
if (screenStateReceiverInstance == null)
screenStateReceiverInstance = new ScreenStateReceiver();
if (screenStateIntentFilter == null)
{
screenStateIntentFilter = new IntentFilter();
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
screenStateIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
screenStateIntentFilter.addAction(Intent.ACTION_USER_PRESENT); // also fired when device is unlocked
screenStateIntentFilter.addAction(broadcastScreenLockedWithoutSecurity);
screenStateIntentFilter.addAction(broadcastScreenLockedWithSecurity);
// Intent.ACTION_USER_UNLOCKED
}
screenStatusIntent = automationServiceRef.registerReceiver(screenStateReceiverInstance, screenStateIntentFilter);
screenStateReceiverActive = true;
}
}
public static void stopScreenStateReceiver()
{
if (screenStateReceiverActive)
{
if (screenStateReceiverInstance != null)
{
automationServiceRef.unregisterReceiver(screenStateReceiverInstance);
screenStateReceiverInstance = null;
}
screenStateReceiverActive = false;
}
}
public static boolean isScreenStateReceiverActive()
{
return screenStateReceiverActive;
}
public static int getScreenPowerState()
{
return screenPowerState;
}
public static int getScreenLockState()
{
return screenLockState;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
@Override
public void onReceive(Context context, Intent intent)
{
if (intent == null)
return;
if (context == null)
return;
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Received: " + intent.getAction(), 3);
try
{
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
ScreenStateReceiver.screenPowerState = SCREEN_STATE_OFF;
KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
// PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
// Miscellaneous.logEvent("i", "ScreenStateReceiver", "Method 2: " + String.valueOf(pm.isInteractive() && pm.isScreenOn() && keyguardManager.isKeyguardLocked() && keyguardManager.isDeviceLocked()), 4);
// if (pm.isInteractive() && pm.isScreenOn() && keyguardManager.isKeyguardLocked() && keyguardManager.isDeviceLocked())
// Miscellaneous.logEvent("i", "ScreenStateReceiver", "pm.isInteractive(): " + String.valueOf(pm.isInteractive()), 4);
// Miscellaneous.logEvent("i", "ScreenStateReceiver", "pm.isScreenOn(): " + String.valueOf(pm.isScreenOn()), 4);
Miscellaneous.logEvent("i", "ScreenStateReceiver", "keyguardManager.isKeyguardLocked(): " + String.valueOf(keyguardManager.isKeyguardLocked()), 4);
Miscellaneous.logEvent("i", "ScreenStateReceiver", "keyguardManager.isDeviceLocked(): " + String.valueOf(keyguardManager.isDeviceLocked()), 4);
if(keyguardManager.isKeyguardLocked() && !keyguardManager.isDeviceLocked())
{
Actions.sendBroadcast(Miscellaneous.getAnyContext(), broadcastScreenLockedWithoutSecurity);
}
else if(keyguardManager.isDeviceLocked())
{
Actions.sendBroadcast(Miscellaneous.getAnyContext(), broadcastScreenLockedWithSecurity);
}
else
{
// Lock may be activated delayed, not at power button press
ScreenLockMonitor mon = new ScreenLockMonitor();
mon.startMonitor();
}
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
ScreenStateReceiver.screenPowerState = SCREEN_STATE_ON;
}
else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT))
{
ScreenStateReceiver.screenLockState = SCREEN_STATE_UNLOCKED;
}
else if (intent.getAction().equals(broadcastScreenLockedWithoutSecurity))
{
ScreenStateReceiver.screenLockState = SCREEN_STATE_LOCKED_WITHOUT_SECURITY;
}
else if (intent.getAction().equals(broadcastScreenLockedWithSecurity))
{
ScreenStateReceiver.screenLockState = SCREEN_STATE_LOCKED_WITH_SECURITY;
}
else
{
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Unknown state received: " + intent.getAction(), 3);
}
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Error receiving screen state: " + e.getMessage(), 3);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.screenState);
for (int i = 0; i < ruleCandidates.size(); i++)
{
if (ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
@Override
public void startListener(AutomationService automationService)
{
ScreenStateReceiver.startScreenStateReceiver(automationService);
}
@Override
public void stopListener(AutomationService automationService)
{
ScreenStateReceiver.stopScreenStateReceiver();
}
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission(Manifest.permission.READ_PHONE_STATE, Miscellaneous.getAnyContext()) &&
ActivityPermissions.havePermission(Manifest.permission.BATTERY_STATS, Miscellaneous.getAnyContext());
}
@Override
public boolean isListenerRunning()
{
return ScreenStateReceiver.isScreenStateReceiverActive();
}
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger_Enum[]{Trigger_Enum.screenState};
}
class ScreenLockMonitor
{
long runs = 0;
final long maxRuns = 20;
final long interval = 1000;
Timer timer = new Timer();
TimerTask task = new TimerTask()
{
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
@Override
public void run()
{
KeyguardManager keyguardManager = (KeyguardManager) Miscellaneous.getAnyContext().getSystemService(Context.KEYGUARD_SERVICE);
Miscellaneous.logEvent("i", "ScreenStateReceiver", "keyguardManager.isKeyguardLocked(): " + String.valueOf(keyguardManager.isKeyguardLocked()), 4);
Miscellaneous.logEvent("i", "ScreenStateReceiver", "keyguardManager.isDeviceLocked(): " + String.valueOf(keyguardManager.isDeviceLocked()), 4);
if(keyguardManager.isKeyguardLocked() && !keyguardManager.isDeviceLocked())
{
Actions.sendBroadcast(Miscellaneous.getAnyContext(), broadcastScreenLockedWithoutSecurity);
timer.purge();
timer.cancel();
}
else if(keyguardManager.isDeviceLocked())
{
Actions.sendBroadcast(Miscellaneous.getAnyContext(), broadcastScreenLockedWithSecurity);
timer.purge();
timer.cancel();
}
else
{
if (runs++ > maxRuns)
{
Miscellaneous.logEvent("w", "ScreenStateReceiver->ScreenLockMonitor", "Lock never came.", 4);
timer.purge();
timer.cancel();
}
}
}
};
public void startMonitor()
{
ContentResolver mResolver = Miscellaneous.getAnyContext().getContentResolver();
long lockscreen_timeout = 0;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1)
lockscreen_timeout = Settings.System.getInt(mResolver, "lock_screen_lock_after_timeout", 0);
else
lockscreen_timeout = Settings.Secure.getInt(mResolver, "lock_screen_lock_after_timeout", 0);
if(lockscreen_timeout > 0)
timer.schedule(task, lockscreen_timeout);
else
timer.scheduleAtFixedRate(task, 0, interval);
}
}
}

View File

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

View File

@ -0,0 +1,130 @@
package com.jens.automation2.receivers;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.util.Log;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
public class TetheringReceiver extends android.content.BroadcastReceiver implements AutomationListenerInterface
{
public static AutomationService automationServiceRef = null;
private static boolean receiverActive = false;
private static TetheringReceiver receiverInstance = null;
private static IntentFilter intentFilter = null;
private static boolean tetheringActive = false;
public static TetheringReceiver getInstance()
{
if(receiverInstance == null)
receiverInstance = new TetheringReceiver();
return receiverInstance;
}
public static boolean isTetheringActive()
{
return tetheringActive;
}
@Override
public void onReceive(Context context, Intent intent)
{
for(String key : intent.getExtras().keySet())
{
// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
Object ob = intent.getExtras().get(key);
String target = null;
if(Build.VERSION.SDK_INT >= 26)
target = "tetherArray";
else
target = "activeArray";
if(key.equals(target) && ob instanceof ArrayList)
{
if(((ArrayList<String>)ob).size() > 0)
tetheringActive = true;
else
tetheringActive = false;
}
// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.tethering);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
@Override
public void startListener(AutomationService automationService)
{
if(!receiverActive)
{
TetheringReceiver.automationServiceRef = automationService;
if(receiverInstance == null)
receiverInstance = new TetheringReceiver();
if(intentFilter == null)
{
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.TETHER_STATE_CHANGED");
}
try
{
automationServiceRef.registerReceiver(receiverInstance, intentFilter);
receiverActive = true;
}
catch(Exception e)
{
/*
We might be confronted with permission issues here.
*/
Miscellaneous.logEvent("e", "TetheringReceiver", Log.getStackTraceString(e), 1);
receiverActive = false;
}
}
}
@Override
public void stopListener(AutomationService automationService)
{
if(receiverActive)
{
if(receiverInstance != null)
{
automationServiceRef.unregisterReceiver(receiverInstance);
receiverInstance = null;
}
receiverActive = false;
}
}
@Override
public boolean isListenerRunning()
{
return receiverActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[] { Trigger.Trigger_Enum.tethering};
}
}

View File

@ -14,14 +14,13 @@ import com.jens.automation2.Trigger.Trigger_Enum;
public class TimeZoneListener extends BroadcastReceiver implements AutomationListenerInterface
{
private static TimeZoneListener timeZoneListenerInstance = null;
protected static boolean timeZoneListenerActive = false;
protected static boolean timezoneListenerActive = false;
protected static AutomationService automationServiceRef = null;
protected static IntentFilter timeZoneListenerIntentFilter = null;
protected static IntentFilter timezoneListenerIntentFilter = null;
public static boolean isTimeZoneListenerActive()
public static boolean isTimezoneListenerActive()
{
return timeZoneListenerActive;
return timezoneListenerActive;
}
public static void startTimeZoneListener(AutomationService automationService)
@ -33,19 +32,19 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
try
{
if(!timeZoneListenerActive && Rule.isAnyRuleUsing(Trigger_Enum.timeFrame))
if(!timezoneListenerActive && Rule.isAnyRuleUsing(Trigger_Enum.timeFrame))
{
Miscellaneous.logEvent("i", "TimeZoneListener", "Starting TimeZoneListener", 4);
timeZoneListenerActive = true;
timezoneListenerActive = true;
if(timeZoneListenerIntentFilter == null)
if(timezoneListenerIntentFilter == null)
{
timeZoneListenerIntentFilter = new IntentFilter();
timeZoneListenerIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
timeZoneListenerIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
timezoneListenerIntentFilter = new IntentFilter();
timezoneListenerIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
timezoneListenerIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
}
automationService.registerReceiver(timeZoneListenerInstance, timeZoneListenerIntentFilter);
automationService.registerReceiver(timeZoneListenerInstance, timezoneListenerIntentFilter);
}
}
catch(Exception ex)
@ -57,11 +56,11 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
{
try
{
if(timeZoneListenerActive)
if(timezoneListenerActive)
{
Miscellaneous.logEvent("i", "TimeZoneListener", "Stopping TimeZoneListener", 4);
automationServiceRef.unregisterReceiver(timeZoneListenerInstance);
timeZoneListenerActive = false;
timezoneListenerActive = false;
}
}
catch(Exception ex)
@ -81,7 +80,7 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
}
else if(action.equals(Intent.ACTION_TIME_CHANGED))
{
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 4);
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 3);
DateTimeListener.reloadAlarms();
}
}
@ -104,7 +103,7 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
@Override
public boolean isListenerRunning()
{
return TimeZoneListener.isTimeZoneListenerActive();
return TimeZoneListener.isTimezoneListenerActive();
}
@Override
public Trigger_Enum[] getMonitoredTrigger()

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

View File

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

View File

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

View File

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

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/createNotification"
android:textSize="25dp"
android:layout_marginBottom="@dimen/default_margin" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/title" />
<EditText
android:id="@+id/etNotificationTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</TableRow>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/text" />
<EditText
android:id="@+id/etNotificationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</TableRow>
</TableLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvLegend"
android:layout_width="match_parent"
android:layout_height="0dip"
android:text="@string/urlLegend" />
</ScrollView>
<Button
android:id="@+id/bSaveActionNotification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/runExecutable" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/runExecutableExplanation" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:shrinkColumns="1">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/runAsRoot" />
<CheckBox
android:id="@+id/chkRunExecAsRoot"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</CheckBox>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/path" />
<EditText
android:id="@+id/etRunExecutablePath"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textUri" >
</EditText>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/parameters" />
<EditText
android:id="@+id/etRunExecutableParameters"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text" >
</EditText>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bChooseExecutable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/chooseExecutable" />
<ScrollView
android:layout_marginTop="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvLegend"
android:layout_width="match_parent"
android:layout_height="0dip"
android:text="@string/urlLegend" />
</ScrollView>
<Button
android:id="@+id/bSaveActionRunExec"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/sendBroadcast" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/broadcastExplanation" />
<TextView
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Broadcast:" />
<EditText
android:id="@+id/etBroadcastToSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/bBroadcastSendShowSuggestions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/broadcastsShowSuggestions" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:stretchColumns="1"
android:shrinkColumns="1" >
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/addParameters" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_span="2"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/intentDataComment" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/parameterType" />
<Spinner
android:id="@+id/spinnerParameterType"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvCurrentNfcIdValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/parameterName" />
<EditText
android:id="@+id/etParameterName"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/parameterValue" />
<EditText
android:id="@+id/etParameterValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
<Button
android:id="@+id/bAddIntentPair"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addIntentValue" />
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:background="#aa000000" />
<ListView
android:id="@+id/lvIntentPairs"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="115dp"
android:layout_marginBottom="@dimen/default_margin" />
<Button
android:id="@+id/bSaveSendBroadcast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -2,13 +2,22 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_margin="10dp" >
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/actionSpeakText" />
<TextView
android:id="@+id/tvRuleTitle"
android:layout_width="wrap_content"
@ -40,7 +49,7 @@
</ScrollView>
<Button
android:id="@+id/bSaveTriggerUrl"
android:id="@+id/bSaveSpeakText"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -110,7 +110,7 @@
</ScrollView>
<Button
android:id="@+id/bSaveTriggerUrl"
android:id="@+id/bSaveSpeakText"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/actionSetWifi"/>
<TextView
android:id="@+id/tvWifiExplanation1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/wifiExplanation1" />
<TextView
android:id="@+id/tvWifiExplanation2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/wifiExplanation2" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:stretchColumns="1"
android:shrinkColumns="1" >
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/runAsRoot" />
<CheckBox
android:id="@+id/chkWifiRunAsRoot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/runAsRoot" />
</TableRow>
<TableRow
android:layout_marginTop="@dimen/default_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/state" />
<RadioGroup
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbActionWifiOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/on" />
<RadioButton
android:id="@+id/rbActionWifiOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/off" />
</RadioGroup>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bActionWifiSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -46,7 +46,7 @@
android:orientation="horizontal" >
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/latitude"
@ -57,7 +57,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="numberSigned" />
android:inputType="text" />
</TableRow>
@ -78,7 +78,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="numberSigned" />
android:inputType="text" />
</TableRow>
<TableRow

View File

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

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="@dimen/default_margin">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/broadcastReceivedTitle" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/explanationBroadcastTrigger" />
<TextView
android:id="@+id/tvBroadcastUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/broadcastListUrl" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbBroadcastReceived"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/broadcastReceived" />
<RadioButton
android:id="@+id/rbBroadcastNotReceived"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/broadcastNotReceived" />
</RadioGroup>
<EditText
android:id="@+id/etBroadcastTriggerAction"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bBroadcastShowSuggestions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/broadcastsShowSuggestions" />
<Button
android:id="@+id/bSaveTriggerBroadcast"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</androidx.appcompat.widget.LinearLayoutCompat>
</ScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

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

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/tetheringState"/>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:stretchColumns="1"
android:shrinkColumns="1" >
<TableRow
android:layout_marginTop="@dimen/default_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/state" />
<RadioGroup
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbTetheringOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/on" />
<RadioButton
android:id="@+id/rTetheringOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/off" />
</RadioGroup>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bTriggerTetheringSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -23,7 +23,7 @@
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/end"
@ -78,6 +78,13 @@
android:text="@string/timeFrameWhichDays"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvDaysHint"
android:layout_marginVertical="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/red" />
<CheckBox
android:id="@+id/checkMonday"
android:layout_width="wrap_content"

View File

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

View File

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

View File

@ -193,7 +193,7 @@
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvTimeFrameHelpText"
android:id="@+id/tvLastRule"
android:layout_width="0dip"
android:layout_weight="5"
android:layout_height="wrap_content"
@ -204,6 +204,34 @@
android:textSize="20dp" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="20dp" >
<TextView
android:layout_width="0dip"
android:layout_weight="5"
android:layout_height="wrap_content"
android:gravity="right"
android:text="@string/lastProfile"
android:scrollHorizontally="false"
android:singleLine="false"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvLastProfile"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="5"
android:scrollHorizontally="false"
android:singleLine="false"
android:text="n./a."
android:textSize="20dp" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -327,11 +355,11 @@
android:text="@string/privacy" />
<Button
android:id="@+id/bSettings"
android:id="@+id/bControlCenter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:text="@string/settings" />
android:text="@string/controlCenter" />
<Button
android:id="@+id/bDonate"
@ -341,6 +369,13 @@
android:layout_gravity="top"
android:text="@string/donate" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:gravity="center_horizontal"
android:text="@string/emailContactNotice" />
</LinearLayout>
</LinearLayout>

View File

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

View File

@ -11,7 +11,7 @@
<string name="pleaseSpecifiyTrigger">Bitte geben Sie mindestens einen Auslöser an.</string>
<string name="pleaseSpecifiyAction">Bitte geben Sie mindestens eine Aktion an.</string>
<string name="serviceWontStart">Weder Orte noch Regeln sind definitiv. Dienst wird nicht starten.</string>
<string name="serviceStarted">Automations-Dienst gestarted.</string>
<string name="serviceStarted">Automations-Dienst gestartet.</string>
<string name="version">Version %1$s.</string>
<string name="distanceBetween">Der Abstand zwischen GPS- und Mobilfunk-Position beträgt %1$d m. Dies +1 sollte der minimale Radius sein.</string>
<string name="positioningWindowNotice">Falls Sie in einem Gebäude sind, wird empfohlen das Gerät in die Nähe eines Fensters zu bringen bis eine Position ermittelt werden konnte. Andernfalls kann es sehr lange dauern oder es funktioniert gar nicht.</string>
@ -57,7 +57,7 @@
<string name="end">Ende</string>
<string name="save">Speichern</string>
<string name="urlToTrigger">URL, die ausgelöst werden soll:</string>
<string name="urlLegend">Variablen:\nSie können die folgenden Variablen verwenden. Vor dem Auslösen werden sie mit dem entsprechenden Wert Ihres Geräts ersetzt. Die Klammern müssen in den Text mit aufgenommen werden.\n\n[uniqueid] - Die Unique ID Ihres Geräts\n[serialnr] - Die Seriennummer Ihres Geräts\n[latitude] - Ihr gegenwärtiger Breitengrad\n[longitude] - Ihr gegenwärtiger Längengrad\n[phonenr] - Nummer des letzten ein- oder ausgehenden Anrufs\n[d] - Tag des Monats, 2-stellig mit führender Null\n[m] - Monat als Zahl, mit führenden Nullen\n[Y] - Vierstellige Jahreszahl\n[h] - Stunde im 12-Stunden-Format, mit führenden Nullen\n[H] - Stunde im 24-Stunden-Format, mit führenden Nullen\n[i] - Minuten, mit führenden Nullen\n[s] - Sekunden, mit führenden Nullen\n[ms] - milliseconds\n[notificationTitle] - Titel der letzten Benachrichtigung\n[notificationText] - Text der letzten Benachrichtigung</string>
<string name="urlLegend">Variablen:\nSie können die folgenden Variablen verwenden. Vor dem Auslösen werden sie mit dem entsprechenden Wert Ihres Geräts ersetzt. Die Klammern müssen in den Text mit aufgenommen werden.\n\n[uniqueid] - Die Unique ID Ihres Geräts\n[serialnr] - Die Seriennummer Ihres Geräts (&lt; Android 9)\n[latitude] - Ihr gegenwärtiger Breitengrad\n[longitude] - Ihr gegenwärtiger Längengrad\n[phonenr] - Nummer des letzten ein- oder ausgehenden Anrufs\n[d] - Tag des Monats, 2-stellig mit führender Null\n[m] - Monat als Zahl, mit führenden Nullen\n[Y] - Vierstellige Jahreszahl\n[h] - Stunde im 12-Stunden-Format, mit führenden Nullen\n[H] - Stunde im 24-Stunden-Format, mit führenden Nullen\n[i] - Minuten, mit führenden Nullen\n[s] - Sekunden, mit führenden Nullen\n[ms] - milliseconds\n[notificationTitle] - Titel der letzten Benachrichtigung\n[notificationText] - Text der letzten Benachrichtigung</string>
<string name="wifi">WLAN</string>
<string name="activating">Aktiviere</string>
<string name="deactivating">Deaktiviere</string>
@ -403,7 +403,7 @@
<string name="startNewThreadForRuleExecution">Für Regelaktivierung neuen Thread starten.</string>
<string name="newThreadRules">Neuer Thread</string>
<string name="showIcon">Symbol</string>
<string name="showIconWhenServiceIsRunning">Symbol anzeigen, wenn Dienst läuft (verstecken funktioniert nur unterhalb Android 7)</string>
<string name="showIconWhenServiceIsRunning">Symbol anzeigen, wenn Dienst läuft (verstecken funktioniert nur unterhalb Android 7). Wenn Sie auf einer höheren Version sind, gehen Sie in die System Einstellungen, dann Automation und dann Benachrichtigungen. Deaktivieren Sie die \"Service notification\".</string>
<string name="ruleHistory">Regel Historie (letzte zuerst):</string>
<string name="someOptionsNotAvailableYet">Manche Optionen sind deaktiviert, da sie noch nicht funktionieren. Sie kommen in einer späteren Programmversion dazu.</string>
<string name="lockSoundChanges">Tonänderungen sperren</string>
@ -413,7 +413,7 @@
<string name="volumeTest">Lautstärkekalibrierung</string>
<string name="volumeCalibrationExplanation">Um einen dB Wert für die Lautstärkemessung zu berechnen müssen Sie einen sogenannten physikalischen Referenzwert angeben. Bitte lesen Sie bei Wikipedia nach, um mehr zu erfahren. Dieser Wert wird höchstwahrscheinlich für jedes Smartphone oder Tablet anders sein, deshalb diese Testanwendung. Verschieben Sie den Regler, um den gegenwärtig definierten Wert zu ändern. Je höher der Referenzwert desto niedriger wird der dB Wert. Es werden alle paar %1$s Sekunden neue Messungen vorgenommen und das Ergebnis unten angezeigt. Drücken Sie den zurück-Button, wenn Sie einen passenden Wert gefunden haben.</string>
<string name="settingsWillTakeTime">Manche Einstellungen können nicht übernommen werden bevor der Dienst neu gestartet wird.</string>
<string name="rootExplanation">Sie müssen Ihr Telefon rooten, damit diese Funktion funktionieren kann. Danach müssen Sie "Regel manuell ausführen", um den SuperUser Berechtigungsdialog zu zeigen. Wenn dieser erscheint, müssen Sie den Haken setzen, der es immer erlaubt. Ansonsten kann die Regel nicht funktionieren, wenn Sie das Telefon gerade nicht benutzen und demnach den nächsten Dialog nicht genehmigen können.</string>
<string name="rootExplanation">Sie müssen Ihr Telefon rooten, damit diese Funktion funktionieren kann. Danach müssen Sie die Regel manuell ausführen, um den SuperUser Berechtigungsdialog zu zeigen. Wenn dieser erscheint, müssen Sie den Haken "immer erlauben" setzen. Ansonsten wird die Regel nicht funktionieren, wenn Sie das Telefon gerade nicht benutzen.</string>
<string name="errorWritingConfig">Fehler beim Schreiben der Konfiguration. Gibt es einen beschreibbaren Speicher, und wurde alle Berechtigungen gegeben?</string>
<string name="phoneNrReplacementError">Die letzte Telefonnummer konnte nicht in die Variable integriert werden. Sie liegt mir nicht vor.</string>
<string name="username">Benutzername</string>
@ -532,7 +532,7 @@
<string name="fileDoesNotExist">Datei existiert nicht.</string>
<string name="noFileManageInstalled">Kein Dateimanager installiert.</string>
<string name="alwaysPlayExplanation">Wenn diese Einstellung aktiv ist, wird der Ton immer abgespielt. Wenn die Einstellung inaktiv ist, wird der Ton nur dann abgespielt, wenn das Telefon weder auf stumm noch auf Vibration steht, d.h. Klingeltöne aktiv sind. Allerdings hat es keinen Einfluß auf die Medien-Lautstärke. D.h., wenn diese stumm ist, werden Sie so oder so nichts zu hören bekommen.</string>
<string name="shareConfigAndLogFilesWithDev">Konfigurations- und Logdatei mit Entwickler teilen (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Konfigurations- und Logdateien anhängen</string>
<string name="shareConfigAndLogExplanation">Dies wird eine neue Email öffnen mit Konfigurations- und Logdateien als Zip-Anhang. Sie wird nicht automatisch versendet. D.h. Sie können so z.B. auch den Adressaten zu sich selbst ändern.</string>
<string name="notificationTriggerExplanation">Dieser Auslöser reagiert auf Benachrichtigungen anderer Anwendung im Benachrichtigungsbereich von Android (oder wenn diese geschlossen werden). Sie können eine bestimmte Anwendung festlegen, von die Nachricht stammen muß. Wenn nicht, zählt jede Benachrichtigung. Sie können auch Zeichenketten für Titel oder Nachrichteninhalt festlegen, die enthalten sein müssen. Die Groß-/Kleinschreibung wird hierbei nicht berücksichtigt.</string>
<string name="addParameters">Parameter hinzufügen</string>
@ -557,7 +557,7 @@
<string name="noFilesImported">Keine Dateien konnten importiert werden.</string>
<string name="notAllFilesImported">Nicht alle passenden Dateien konnten importiert werden.</string>
<string name="openExamplesPage">Webseite mit Beispielen öffnen</string>
<string name="phoneNumberExplanation">Sie können eine bestimmte Nummer eingeben, aber müssen nicht. Wenn Sie eine angeben wollen, können Sie auch eine aus dem Adressbuch auswählen. Außerdem können Sie reguläre Audrücke verwenden. Zum Testen selbiger mag ich die Seite:</string>
<string name="phoneNumberExplanation">Sie können eine bestimmte Nummer eingeben (des Anrufpartners), aber müssen nicht. Wenn Sie eine angeben wollen, können Sie auch eine aus dem Adressbuch auswählen. Außerdem können Sie reguläre Audrücke verwenden. Zum Testen selbiger mag ich die Seite:</string>
<string name="prefsImportError">Fehler beim Importieren der Einstellungen.</string>
<string name="rulesImportedSuccessfully">Regeln und Orte wurden erfolgreich importiert.</string>
<string name="rulesImportError">Fehler beim Importieren der Regeln.</string>
@ -648,7 +648,7 @@
<string name="profileNotActive">Profil %1$s ist nicht aktiv</string>
<string name="profileTriggerCheckSettings">Wenn dieses Häkchen nicht gesetzt ist, wird nur geprüft, ob das ausgewählte Profil zuletzt aktiviert wurde. Es ist egal, ob Audio-Einstellungen von außerhalb verändert wurden.\nWenn das Häkchen aber gesetzt ist, müssen die aktuellen Audio-Einstellungen auch wirklich genau so gesetzt sein, wie im Profil definiert. ACHTUNG: Der Klingelton selbst kann derzeit noch nicht überprüft werden.</string>
<string name="profileCouldNotBeDeleted">Profil konnte nicht gelöscht werden.</string>
<string name="ruleXIsUsingProfileY">Dieses Profil kann nicht gelöscht werden. Regel %s$1 verwendet noch Profil %s$2.</string>
<string name="ruleXIsUsingProfileY">Dieses Profil kann nicht gelöscht werden. Regel %1$s verwendet noch Profil %2$s.</string>
<string name="noRepetition">keine Wiederholung</string>
<string name="usingAuthentication">mit Authentifizierung</string>
<string name="toNumber">zu Nummer</string>
@ -659,4 +659,82 @@
<string name="pickActivityManually">Manuell auswählen</string>
<string name="launcherOrManualExplanation">Einfacher Modus: Automation kann versuchen, die Start-Activity des Zielprogramms automatisch zu finden.\nAlternativ können Sie die gewünschte Activity auch manuell auswählen.\nWelche Variante möchten Sie?</string>
<string name="launcherNotFound">Eine Start-Activity dieser Anwendung konnte nicht gefunden werden. Sie müssen manuell eine auswählen.</string>
<string name="enterTitle">Geben Sie einen Titel ein.</string>
<string name="enterText">Geben Sie einen Text ein.</string>
<string name="info">Info</string>
<string name="createNotification">Benachrichtigung erstellen</string>
<string name="profileWasNotFound">Das Profil, das in dieser Regel referenziert wird, existiert scheinbar nicht mehr. Das alphabetisch erste wurde stattdessen ausgewählt.</string>
<string name="closeNotifications">Benachrichtigung(en) schließen</string>
<string name="comparisonCaseInsensitive">Groß-/Kleinschreibung ist egal.</string>
<string name="notificationCloseActionExplanation">Wenn Sie keine Kriterien angeben, werden ALLE Benachrichtigungen geschlossen. Es wird also empfohlen, zumindest eine Anwendung zu spezifizieren und/oder Titel oder Text anzugeben.</string>
<string name="profileWarning">Die Einstellungen, die Sie hier vornehmen, können dazu führen, dass Sie bestimmte Dinge auf Ihrem Telefon nicht mehr mitbekommen. Sie können sogar Ihren Wecker zum Schweigen bringen. Was auch immer Sie hier einstellen - es wird empfohlen, es zu testen.</string>
<string name="ifString">falls</string>
<string name="pleaseSelectActionValue">Bitte wählen Sie eine Aktion!</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Medien steuern</string>
<string name="play">abspielen</string>
<string name="stop">stop</string>
<string name="next">nächster</string>
<string name="previous">vorheriger</string>
<string name="pause">pausieren</string>
<string name="playPause">abspielen/pause umschalten</string>
<string name="selectCommand">Kommando auswählen</string>
<string name="unlocked">entsperrt</string>
<string name="on">an</string>
<string name="off">aus</string>
<string name="actionMediaControlNotice">Bedenken Sie, daß diese Aktion nicht notwendigerweise mit allen Playern funktioniert. Und selbst, wenn es mit einem grundsätzlich funktioniert, müssen auch nicht alle der u.g. Kommandos funktionieren.</string>
<string name="screenState">Bildschirm Status</string>
<string name="actionMediaControl">Medien steuern</string>
<string name="selectDesiredState">Bitte gewünschten Zustand wählen</string>
<string name="screenIs">Bildschirm ist %1$s</string>
<string name="sendEmailToDev">Email an Entwickler schicken</string>
<string name="controlCenter">Steuerungszentrale</string>
<string name="emailContactNotice">Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Aufgrund Google\'s unendlicher Weisheit, ist die letzte Android Version, mit der diese Funktion noch funktioniert, die Version %1$s. Sie können es hier einrichten, aber vermutlich wird es keine Auswirkung haben.</string>
<string name="musicPlaying">Musik läuft</string>
<string name="selectParameters">Wählen Sie die Parameter</string>
<string name="musicIsPlaying">Musik läuift</string>
<string name="musicIsNotPlaying">Musik läuft nicht</string>
<string name="musicCheckFrequencyTitle">Prüffrequenz</string>
<string name="musicCheckFrequencySummary">Millisekunden zwischen Prüfungen</string>
<string name="musicPlayingDetection">Musik-läuft Erkennung</string>
<string name="locationNotWorkingOn12">Das Abrufen des Standorts scheint unter Android 12 derzeit nicht zu funktionieren. Wenn es bei Ihnen nicht klappt, tut mir das leid. Ich werde versuchen die Ursache zu beheben, sobald mir die Ursache bekannt ist. Wenn der Donut bei Ihnen also nicht aufhört sich zu drehen, wissen Sie warum.</string>
<string name="profileXrequiresThis">Profil \"%1$s\" benötigt dies.</string>
<string name="lastProfile">Letztes Profil:</string>
<string name="queryAllPackages">Liste von installierten Anwendungen auslesen</string>
<string name="timeFrameDaysHint">Wenn Sie ein Zeitfenster verwenden, das sich über Mitternacht erstreckt, müssen Sie auch den Folgetag auswählen, wenn der Auslöser auch nach Mitternacht noch auslösen soll.</string>
<string name="featureNotInGooglePlayVersion">Diese Funktion ist in der Google Play-Version nicht mehr verfügbar.\n\nHin und wieder schikaniert Google Entwickler. Wenn Sie bestimmte Funktionen weiterhin verwenden möchten, müssen Sie Unterlagen einreichen. Leider besteht eine 99% ige Chance, dass der Papierkram abgelehnt wird. Es ist so ziemlich wie im Asterix-Comic/Film.\n\nIch habe in der Vergangenheit Wochen damit verbracht, mit ihnen über solche Fälle zu streiten, aber ich bekam immer wieder Ablehnungen - entweder von Bots oder von Leuten, die ungefähr so intelligent sind wie Bots. Ich kann mich dann nur entscheiden, ob die App vollständig aus dem Play Store fliegen soll oder die Funktion aus der Play Store Version entfernen.\n\nBitte erwägen Sie, die APK-Version von meiner Website oder die von F-Droid zu verwenden, wenn Sie diese Funktionen benötigen.</string>
<string name="startActivityInsertManually">Diese Einschränkung betrifft nur die Auswahl einer App, nicht den eigentlichen Start. So können Sie den Namen einer Anwendung immer noch manuell eingeben, falls Sie ihn kennen.</string>
<string name="serviceStarts">Dienst startet</string>
<string name="deviceStarts">Gerät startet</string>
<string name="deviceHasJustStarted">Gerät ist gerade gestartet</string>
<string name="serviceHasJustStarted">Dienst ist gerade gestartet</string>
<string name="broadcastReceived">Broadcast empfangen</string>
<string name="broadcastNotReceived">Broadcast nicht empfangen</string>
<string name="broadcastReceivedTitle">Broadcast empfangen</string>
<string name="broadcastsShowSuggestions">Vorschläge anzeigen</string>
<string name="selectBroadcast">Broadcast auswählen</string>
<string name="lockedWithoutSecurity">gesperrt (nur wischen, keine PIN, etc.)</string>
<string name="lockedWithSecurity">gesperrt (mit PIN, etc.)</string>
<string name="lockedCommentScreenMustBeOff">Jeglicher Sperrzustand wird nur erkannt werden, wenn gleichzeitig der Bildschirm aus ist.</string>
<string name="emailPretext">Wenn Sie ein Problem, einen Vorschlag oder eine Frage haben, schreiben Sie bitte auch etwas in die Email. Senden Sie mir nicht einfach die Dateien mit dem Standard-Mailtext. Ich werde solche Nachrichten ignorieren, sollten wir nicht bereits in einer Konversation sein.</string>
<string name="sendBroadcast">Broadcast verschicken</string>
<string name="enterBroadcast">Geben Sie eine Aktion für den Broadcast ein.</string>
<string name="broadcastExplanation">Diese Aktion erlaubt es, einen Broadcast über das Nachrichtensystem von Android zu verschicken. Das ist für den Benutzer nicht sichtbar, aber Anwendungen, die sich für bestimmte Broadcasts registriert haben, können darauf reagieren.</string>
<string name="explanationBroadcastTrigger">La mayoría de los eventos en su teléfono se \"publicado\" transmitiéndolos a través del sistema operativo.\nPor ejemplo, activar / desactivar el modo avión activará dicha transmisión. Esas transmisiones no son automáticamente visibles / audibles, pero si una aplicación (como Automatización) está interesada, puede conectarse a ellas. Cuando ocurran, se le notificará y podrá reaccionar.\n\nPuede definir aquí un evento de difusión para el que la aplicación esperará. Puede ingresarlo manualmente, copiarlo y pegarlo desde algún lugar o elegir uno de la lista de sugerencias. Como este desencadenante está destinado a ser y seguir siendo muy flexible, no puedo proporcionarle explicaciones para los elementos.\n\nLa lista de sugerencias no pretende estar completa. Visite la siguiente URL para echar un vistazo a la documentación de Android.\nTambién cualquier aplicación puede enviar eventos personalizados que no aparecerán en la documentación de Android, por supuesto.\n\nMuchas transmisiones requieren permisos específicos para funcionar. Intento solicitar permisos donde sé que serán necesarios. Si cree que se requiere un permiso para la acción que ingresó, hágamelo saber.\n\nNo recibido significa que no ha habido tal transmisión desde que se inició el servicio. Responder a ciertos parámetros está en desarrollo.</string>
<string name="logsExplanation">Um eine unnötige Abnutzung Ihres Speichers zu vermeiden, werden Protokolle standardmäßig nicht gespeichert. Wenn Sie also ein Problem haben, aktivieren Sie bitte zuerst die Anmeldeeinstellungen und setzen Sie den Protokollpegel auf 5. Reproduzieren Sie dann das Problem. Erst dann können Protokolle angehängt werden.</string>
<string name="directionStringDoesNotContain">enthält nicht</string>
<string name="path">Pfad</string>
<string name="runExecutable">Programm/Script ausführen</string>
<string name="parameters">Parameter</string>
<string name="chooseExecutable">Datei auswählen</string>
<string name="runAsRoot">Als root ausführen</string>
<string name="selectValidExecutable">Wählen Sie eine gültige ausführbare Datei aus.</string>
<string name="fileNotExecutable">Diese Datei ist nicht ausführbar.</string>
<string name="usingRoot">als root</string>
<string name="tetheringActive">Tethering ist aktiv</string>
<string name="tetheringNotActive">Tethering ist nicht aktiv</string>
<string name="tetheringState">Tethering Status</string>
<string name="wifiExplanation2">Während der Flugmodus aktiv ist, kann WLAN nur von Anwendungen ein- oder ausgeschaltet werden, wenn root-Rechte dafür verwendet werden.</string>
<string name="wifiExplanation1">Anwendungen, die auf Android Q oder höher ausgerichtet sind, können WLAN nicht mehr ein- oder ausschalten. Daran ist Google schuld, nicht ich.\n\nSie können diese Einschränkung umgehen, indem Sie Ihr Gerät rooten und die Checkbox unten aktivieren. Alternativ laden Sie sich diese Anwendung von F-Droid oder meiner Webseite herunter. In diesen Versionen bin ich nicht gezwungen, die Anwendungen auf die neuesten API Level zu unterstützen.</string>
<string name="runExecutableExplanation">Sie können ein Script oder eine andere ausführbare Datei auswählen, die dann als Aktion ausgeführt wird.\n\nAllerdings gibt es ein paar Voraussetzungen, um die Sie sich selbst kümmern müssen. Google hat es sehr schwer gemacht, irgendetwas außer normalen Android Anwendungen auszuführen.\n\n1.\nDie Datei muß im Dateisystem als ausführbar markiert sein. Auf einem normalen Android-System (ohne Root) ist das in der Tat der schwierigste Teil.\n\n2.\nDas bedeutet auch, daß auch Automation in der Lage sein muß, die Datei auszuführen, nicht nur der Besitzer oder die Gruppe.\n\n3.\nWenn es ein Script ist, muß eine gültige Shell im Header des Scripts definiert sein.</string>
</resources>

View File

@ -127,10 +127,10 @@
<string name="actionTurnWifiTetheringOff">desactivar enrutador wifi</string>
<string name="actionTurnAirplaneModeOn">encender modo de vuelo</string>
<string name="actionTurnAirplaneModeOff">desactivar modo de vuelo</string>
<string name="activePoi">sitio activo</string>
<string name="activePoi">Sitio activo:</string>
<string name="closestPoi">sitio mas cerca</string>
<string name="poi">Posición</string>
<string name="pois">posiciónes</string>
<string name="pois">Posiciones</string>
<string name="serviceNotRunning">Servicio no está activo</string>
<string name="general">General</string>
<string name="startServiceAfterAppUpdate">Encender servicio después de un update si estuvo activado.</string>
@ -294,7 +294,7 @@
<string name="parameterValue">Valor del parámetro</string>
<string name="addIntentValue">Añadir pareja intento</string>
<string name="parameterType">Tipo del parámetro</string>
<string name="phoneNumberExplanation">Puedes introducir un número, pero es opciónal. Si quieres usar uno puedes elegir uno de su directorio o introducir uno manualmente. Adiciónalmente puedes usar expresiónes regulares. Para probar esos me gusta la pagina:</string>
<string name="phoneNumberExplanation">Puedes introducir un número remoto, pero es opciónal. Si quieres usar uno puedes elegir uno de su directorio o introducir uno manualmente. Adiciónalmente puedes usar expresiónes regulares. Para probar esos me gusta la pagina:</string>
<string name="screenRotationEnabled">Rotación del monitor activado.</string>
<string name="screenRotationDisabled">Rotación del monitor desactivado.</string>
<string name="noPoisDefinedShort">No hay sitios.</string>
@ -358,12 +358,12 @@
<string name="networkAccuracy">Red exactitud [m]</string>
<string name="minimumTimeForLocationUpdates">Tiempo mínimo para cambio en milisegundos para actualizar posición</string>
<string name="timeForUpdate">Tiempo para actualizar [milisegundos]</string>
<string name="urlLegend">Variables: Puede usar esas variables. Mientras ejecuta van a sustituir con los valores correspondientes en su dispositivo. Incluya las paréntecis en su texto. [uniqueid] - el número único de su dispositivo [serialnr] - el número de serie de su dispositivo [latitude] - su latitud [longitude] - su longitud [phonenr] - Ùltimo número de llamada realizada tanto de salida como entrante [d] - Dia del mes, 2 digitos con cero al comienzo [m] - número del mes, 2 digitos con cero al comienzo [Y] - Número del año, 4 digitos [h] - Hora, formato 12 horas con cero al comienzo [H] - Hora, formato 24 horas con cero al comienzo [i] - Minutos con cero al comienzo [s] - Segundos con cero al comienzo [ms] - milisegundos [notificationTitle] - Título de la última notificación [notificationText] - Texto de la última notificación</string>
<string name="urlLegend">Variables: Puede usar esas variables. Mientras ejecuta van a sustituir con los valores correspondientes en su dispositivo. Incluya las paréntecis en su texto.\n\n[uniqueid] - el número único de su dispositivo\n[serialnr] - el número de serie de su dispositivo (&lt; Android 9)\n[latitude] - su latitud\n[longitude] - su longitud\n[phonenr] - Ùltimo número de llamada realizada tanto de salida como entrante\n[d] - Dia del mes, 2 digitos con cero al comienzo\n[m] - número del mes, 2 digitos con cero al comienzo\n[Y] - Número del año, 4 digitos\n[h] - Hora, formato 12 horas con cero al comienzo\n[H] - Hora, formato 24 horas con cero al comienzo\n[i] - Minutos con cero al comienzo\n[s] - Segundos con cero al comienzo\n[ms] - milisegundos\n[notificationTitle] - Título de la última notificación\n[notificationText] - Texto de la última notificación</string>
<string name="screenRotationAlreadyEnabled">Rotación del monitor todavia esta activado.</string>
<string name="screenRotationAlreadyDisabled">Rotación del monitor todavia esta desactivado.</string>
<string name="needLocationPermForWifiList">Se puede usar la lista de wifis conocidos para determinar los sitios en los cuales estuvo. Por eso el permiso de localización es necesario para cargar la lista de wifis. Si quiere elegir uno de la lista tiene que conceder el permiso. En caso contrario todavia puede introducir un nombre wifi manualmente.</string>
<string name="com.wireguard.android.permission.CONTROL_TUNNELS">Controlar conexiones de la app Wireguard</string>
<string name="shareConfigAndLogFilesWithDev">Enviar configuración y procotolo al desarollador (vía email).</string>
<string name="shareConfigAndLogFilesWithDev">Adjuntar configuración y procotolo.</string>
<string name="rootExplanation">Necesita permiso root para esta función. Después encienda la función \"ejecutar regla manualmente\" para presentar el permiso superuser dialogo. Es necesario elegir \"siempre permitir root para esta app\". En caso contrario la regla no puede funcionar en segundo plano.</string>
<string name="helpTextRules">Todas las condiciones están \"Y\"-conectadas. La regla solo va a aplicarse cuando todas las condiciones se aplican. Si quiere \"O\", cree otra regla.</string>
<string name="timeBetweenNoiseLevelMeasurementsSummary">Segundos entre dos ensayos de nivel de ruido</string>
@ -470,7 +470,7 @@
<string name="noMapsApplicationFound">Parece que no hay una aplicación de mapa en su dispositivo.</string>
<string name="soundMode">Modo de sonido de llamada.</string>
<string name="showIcon">Monstrar icono</string>
<string name="showIconWhenServiceIsRunning">Monstrar icono cuando el servicio esta activo (ocultando solo funciona antes Android 7)</string>
<string name="showIconWhenServiceIsRunning">Monstrar icono cuando el servicio esta activo (ocultando solo funciona antes Android 7). Si está en una versión superior, vaya a configuración del sistema, luego Automatización, luego notificaciones y deshabilite \"Service notification\".</string>
<string name="currentVolume">Volumen actual</string>
<string name="volumeTest">Calibrado de volumen</string>
<string name="permissionsTitle">Permisos necesarios</string>
@ -588,7 +588,7 @@
<string name="vibrate">Vibrar</string>
<string name="test">Probar</string>
<string name="VibrateExplanation">Elija la duración de la vibración, seguido de un coma y una duración de una pausa. Puedes concatenar tantos como quiere. Separelos con comas tambien. Por ejemplo el patrón 100,500,500,1000,100 va a vibrar 100, esperar 500, vibrar 500, esperar 1000, vibrar 100 ms. Si cree que una vibración está perdida, pruebe incrementar la pausa antes de esta vibración.</string>
<string name="pleaseEnterValidVibrationPattern">Por favor introduzca un patrón de vibración válido.</string>
<string name="pleaseEnterValidVibrationPattern">Por favor inserte un patrón de vibración válido.</string>
<string name="tabsPlacementSummary">Elija done la barra de tabs está puesto.</string>
<string name="intentDataComment">Si su parametro es de tipo Uri y especifica \"IntentData\" como nombre (minúscula/mayáscula no es importante), el parametro no está añadido como un parametro normal con puExtra(), pero estará añadido al intent con setData().</string>
<string name="locationEngineDisabledLong">Desafortunadamente su posición todavia no puede ser determinada. Gratitud va para Google por su sabiduria y amabilidad infinita.\n\nDejenme explicarselo mas. Comenzando con Android 10 un nuevo permiso se introdujo que es necesario para determinar la posición en el fondo (que es necesario para una app como esta). Aunque lo considero una buena idea, conlleva a una chicana para desarolladores.\n\nCuando se esta desarrollando una app se puede intentar calificar para este permiso mientras se sigue un catalogo de condiciones. Desafortunadamente nuevas versiones de mi app fueron rechazadas por un periodo de trés meses. Cumplé todas las condiciones, pero Google\'s mierda servicio para desarolladores afirmó que no. Despues de presentar pruebas, que cumplí con todo, recibí una respuesta de \"No puedo ayudarte mas.\". En algun momento me rendí.\n\nComo consecuencia la version Google Play todavia no sabe usar la locación como una condición. Mi única alternativa fue remover la applicación de Google Play.\n\nLo siento mucho, pero hicé todo lo posible para discutir con un support que no sabe aprobar la prueba de Turing repetidamente.\n\nLa noticia positiva: Usted todavia puede tener todo!\n\nAutomation ahora es open source y se puede encontrar en F-Droid. Es un app store que se preocupa por su privacidad - en vez de solo simular eso. Simplemente guarde su configuración, desinstale la app, instale la de F-Droid, restaure su configuración - terminado.\n\nCliquee aqui para averiguar más:</string>
@ -626,7 +626,7 @@
<string name="automationNotificationsIgnored">Si no elige una aplicación específica, sino que elige \"Cualquier aplicación\", las notificaciones de Automatización se ignorarán para evitar bucles.</string>
<string name="enterRepetitionTime">Debe insertar un valor positivo no decimal para el tiempo de repetición.</string>
<string name="elementSkipped">No se pudo leer un elemento del archivo de configuración. El archivoo puede haber sido creado por una versión más reciente del programa.</string>
<string name="enterValidNumbersIntoAllFields">Introduzca números válidos en todos los campos.</string>
<string name="enterValidNumbersIntoAllFields">Inserte números válidos en todos los campos.</string>
<string name="toleranceOf180OnlyAllowedIn2Fields">Se permite una tolerancia de 180 solo para 2 campos de tolerancia, no para todos los 3. De lo contrario, el disparador SIEMPRE se aplicaría.</string>
<string name="triggerWrong">Hay algo mal con este condición. No se pudo cargar correctamente.</string>
<string name="deviceOrientationTimeAcceptIntervalSummary">Aceptar nuevas señales de movimiento cada x milisegundos</string>
@ -646,7 +646,7 @@
<string name="recommendedForBetterReliability">Recomendado para una mejor fiabilidad</string>
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Excluir de la optimización de la batería</string>
<string name="profileTriggerCheckSettings">Si esta casilla de verificación no está desactivada, solo se marcará si el perfil seleccionado ha sido el último en activarse. No importa si alguna configuración relacionada con el audio se ha cambiado externamente.\nSin embargo, si la casilla de verificación está habilitada, la configuración de audio actual realmente debe ser como se define en el perfil. CUIDADO: La comprobación del archivo de tono de llamada no es compatible actualmente, todavía.</string>
<string name="ruleXIsUsingProfileY">No se puede eliminar este perfil. La regla %s$1 hace referencia al perfil %s$2.</string>
<string name="ruleXIsUsingProfileY">No se puede eliminar este perfil. La regla %1$s hace referencia al perfil %2$s.</string>
<string name="profileCouldNotBeDeleted">No se pudo eliminar el perfil.</string>
<string name="noRepetition">sin repetición</string>
<string name="usingAuthentication">uso de la autenticación</string>
@ -658,4 +658,68 @@
<string name="pickActivityManually">Eligir manualmente</string>
<string name="launcherOrManualExplanation">Modo facil: Automation puede probar identifcar el launcher activity del programa automaticamente.\nAlternativamente puede eligir una de las activities del programa manualmente.\nCual variante queria?</string>
<string name="launcherNotFound">No se puede encontrar una launcher activity. Tiene que elegir una manualmente.</string>
<string name="info">Info</string>
<string name="createNotification">Crear notificación</string>
<string name="enterTitle">Inserte un título.</string>
<string name="enterText">Inserte un texto.</string>
<string name="profileWasNotFound">El perfil utilizado en esta regla ya no parece existir. Se ha seleccionado el primero alfabéticamente.</string>
<string name="notificationCloseActionExplanation">Si no especifica ningún criterio, esta acción cerrará TODAS las notificaciones. Por lo tanto, se recomienda al menos especificar criterios para al menos 1 de la aplicación, título o texto.</string>
<string name="closeNotifications">Cerrar notificación(es)</string>
<string name="comparisonCaseInsensitive">Las comparaciones se realizan sin distinción de mayúsculas y minúsculas</string>
<string name="profileWarning">La configuración que realice aquí puede hacer que ya no note ciertas cosas de su teléfono. Incluso puede silenciar su alarma de despertar. Así que hagas lo que hagas, se recomienda que lo pruebes.</string>
<string name="ifString">si</string>
<string name="on">encendido</string>
<string name="off">apagado</string>
<string name="unlocked">desbloqueado</string>
<string name="play">reproducir</string>
<string name="pause">pausar</string>
<string name="previous">ultimo</string>
<string name="next">proximo</string>
<string name="stop">parar</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Controlar la reproducción de medios</string>
<string name="actionMediaControl">Controlar la reproducción de medios</string>
<string name="pleaseSelectActionValue">Por favor elije una acción!</string>
<string name="playPause">alternar reproducir/pausar</string>
<string name="selectCommand">Elije el comando</string>
<string name="screenState">Estado de la pantalla</string>
<string name="selectDesiredState">Elije el estado deseado</string>
<string name="controlCenter">Centro de control</string>
<string name="screenIs">pantalla esta %1$s</string>
<string name="sendEmailToDev">Enviar email al desrollador</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Debido a la infinita sabiduría de Google, la última versión de Android en la que se sabe que funciona esta función es %1$s. Puede configurarlo, pero probablemente no tendrá ningún efecto.</string>
<string name="emailContactNotice">El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.</string>
<string name="actionMediaControlNotice">Ten en cuenta que esta acción puede no funcionar con TODOS los jugadores. E incluso si lo hace, no todos los botones funcionan necesariamente.</string>
<string name="musicPlaying">Musica esta reproduciendo</string>
<string name="selectParameters">Elije parametros</string>
<string name="musicIsPlaying">musica esta reproduciendo</string>
<string name="musicIsNotPlaying">musica no esta reproduciendo</string>
<string name="musicCheckFrequencyTitle">Frecuencia de los controles</string>
<string name="musicCheckFrequencySummary">Millisegundos entre controles</string>
<string name="musicPlayingDetection">Musica tocando deteción</string>
<string name="locationNotWorkingOn12">Obtener la locación no parece estar funcionando en dispositivos Android 12 actualmente. Si no está funcionando para ti, lo siento. Intentaré arreglar esto tan pronto como conozca la causa. Así que si la rosquilla no deja de girar, ya sabes por qué.</string>
<string name="profileXrequiresThis">El perfil \"%1$s\" requiere esto.</string>
<string name="lastProfile">Último perfil:</string>
<string name="queryAllPackages">Obtener una lista de las aplicaciones instaladas</string>
<string name="timeFrameDaysHint">Si utiliza un marco de tiempo que se extiende más allá de la medianoche, también debe seleccionar el día siguiente si desea que la condición se aplique después de la medianoche.</string>
<string name="featureNotInGooglePlayVersion">Esta función ya no está disponible en la versión de Google Play.\n\nTodo de vez en cuando Google intimida a los desarrolladores. Si desea seguir utilizando ciertas funciones, debe presentar documentos. Desafortunadamente, hay un 99% de posibilidades de que el papeleo sea rechazado. Es más o menos como en el cómic/la película de Astérix.\n\nHe pasado semanas discutiendo con ellos sobre casos como ese en el pasado, pero seguí recibiendo rechazos, ya sea por bots o personas que son tan inteligentes como los bots. En el puedo decidir entre que la aplicación se elimine de Play Store por completo o eliminar la función.\n\nPor favor, considere usar la versión APK de mi sitio web o la de F-Droid si necesita esas características.</string>
<string name="startActivityInsertManually">Esta limitación se refiere solo a la selección de una aplicación, no al inicio real. Por lo tanto, aún puede ingresar el nombre de una aplicación manualmente si lo conoce.</string>
<string name="deviceStarts">Dispositivo esta enciendo</string>
<string name="serviceStarts">Servicio esta enciendo</string>
<string name="deviceHasJustStarted">el dispositivo justamente ha encendido</string>
<string name="serviceHasJustStarted">el servicio justamente ha encendido</string>
<string name="emailPretext">Si tiene un problema, sugerencia o pregunta, escriba algo en el correo electrónico. No solo envíeme los archivos con el cuerpo de correo predeterminado. Ignoraré todo eso a menos que ya estemos en una conversación.</string>
<string name="lockedCommentScreenMustBeOff">Cualquier estado de bloqueo solo se detectará si la pantalla está apagada.</string>
<string name="lockedWithSecurity">bloqueado (con PIN, etc.)</string>
<string name="lockedWithoutSecurity">bloqueado (solo deslizar, sin PIN)</string>
<string name="selectBroadcast">Seleccionar broadcast</string>
<string name="broadcastsShowSuggestions">Mostrar sugerencias</string>
<string name="broadcastReceivedTitle">Broadcast recibido</string>
<string name="broadcastReceived">broadcast recibido</string>
<string name="broadcastNotReceived">broadcast no recibido</string>
<string name="broadcastExplanation">Esta acción permite enviar una transmisión a través del sistema de mensajes de Android. Esto no es visible para el usuario, pero las aplicaciones que se han registrado para ciertas transmisiones pueden responder a ello.</string>
<string name="sendBroadcast">Enviar broadcast</string>
<string name="enterBroadcast">Introduzca una acción de broadcast.</string>
<string name="explanationBroadcastTrigger">La mayoría de los eventos en su teléfono se \"publicado\" transmitiéndolos a través del sistema operativo.\nPor ejemplo, activar / desactivar el modo avión activará dicha transmisión. Esas transmisiones no son automáticamente visibles / audibles, pero si una aplicación (como Automatización) está interesada, puede conectarse a ellas. Cuando ocurran, se le notificará y podrá reaccionar.\n\nPuede definir aquí un evento de difusión para el que la aplicación esperará. Puede ingresarlo manualmente, copiarlo y pegarlo desde algún lugar o elegir uno de la lista de sugerencias. Como este desencadenante está destinado a ser y seguir siendo muy flexible, no puedo proporcionarle explicaciones para los elementos.\n\nLa lista de sugerencias no pretende estar completa. Visite la siguiente URL para echar un vistazo a la documentación de Android.\nTambién cualquier aplicación puede enviar eventos personalizados que no aparecerán en la documentación de Android, por supuesto.\n\nMuchas transmisiones requieren permisos específicos para funcionar. Intento solicitar permisos donde sé que serán necesarios. Si cree que se requiere un permiso para la acción que ingresó, hágamelo saber.\n\nNo recibido significa que no ha habido tal transmisión desde que se inició el servicio. Responder a ciertos parámetros está en desarrollo.</string>
<string name="logsExplanation">Para evitar el uso innecesario del almacenamiento, los registros no se guardan de forma predeterminada. Entonces, si tiene un problema, active primero la configuración de inicio de sesión y establezca el nivel de registro en 5. A continuación, reproduzca el problema. Solo entonces se pueden adjuntar registros.</string>
<string name="directionStringDoesNotContain">no contiene</string>
</resources>

View File

@ -355,7 +355,7 @@
<string name="phoneDirection">Seleziona se\nentrante o uscente</string>
<string name="phoneNrReplacementError">Non ho l\'ultimo numero di telefono e quindi non posso inserirlo nella variabile.</string>
<string name="phoneNumber">Numero di telefono</string>
<string name="phoneNumberExplanation">È possibile inserire un numero di telefono specifico, ma non è necessario. Se vuoi specificarne uno, puoi sceglierlo dalla tua rubrica o inserirlo manualmente. Inoltre puoi usare espressioni regolari. Per testare un\'espressione regolare mi piace questa pagina:</string>
<string name="phoneNumberExplanation">È possibile inserire un numero di telefono remoto specifico, ma non è necessario. Se vuoi specificarne uno, puoi sceglierlo dalla tua rubrica o inserirlo manualmente. Inoltre puoi usare espressioni regolari. Per testare un\'espressione regolare mi piace questa pagina:</string>
<string name="playSound">Esegui suono</string>
<string name="pleaseEnterValidLatitude">Inserisci una latitudine valida.</string>
<string name="pleaseEnterValidLongitude">Inserisci una longitudine valida.</string>
@ -456,10 +456,10 @@
<string name="settingsSetToDefault">Impostazioni predefinite ripristinate.</string>
<string name="settingsWillTakeTime">Alcune impostazioni non saranno applicate prima che alcune impostazioni contestuali cambino o che il servizio venga riavviato.</string>
<string name="shareConfigAndLogExplanation">Questo creerà una email con la tua configurazione e i file di log allegati come file zip. Non sarà inviata automaticamente, dovrai premere \"invia\". Puoi anche cambiare il destinatario con te stesso, per esempio.</string>
<string name="shareConfigAndLogFilesWithDev">Condividere i file di configurazione e di registro con lo sviluppatore (via e-mail).</string>
<string name="shareConfigAndLogFilesWithDev">Allegare i file di configurazione e di registro</string>
<string name="showHelp">Mostra Aiuto</string>
<string name="showIcon">Mostra icona</string>
<string name="showIconWhenServiceIsRunning">Mostra una icona quando il servizio è attivo (nasconderla funziona solo in versioni inferiori ad Android 7)</string>
<string name="showIconWhenServiceIsRunning">Mostra una icona quando il servizio è attivo (nasconderla funziona solo in versioni inferiori ad Android 7). Se hai una versione superiore, vai alle impostazioni di sistema, quindi Automation, e poi seleziona Notifiche, dove potrai disabilitare la \"Service notification\".</string>
<string name="showOnMap">Mostra sulla mappa</string>
<string name="someOptionsNotAvailableYet">Alcune opzioni sono disabilitate in quanto non ancora implementate. Saranno introdotte in una versione successiva.</string>
<string name="soundMode">Modalità sonora</string>
@ -533,7 +533,7 @@
<string name="tuesday">Martedì</string>
<string name="unknownError">Errore indeterminato.</string>
<string name="until">finchè</string>
<string name="urlLegend">Variabili:\n È possibile utilizzare le seguenti variabili. All\'attivazione saranno sostituite con il valore corrispondente sul dispositivo. Includi le parentesi nel tuo testo.\n\n[uniqueid] - Il numero di serie del tuo dispositivo\n[serialnr] - Il serial number del tuo dispositivio\n[latitude] - La latitudine del tuo dispositivo\n[longitude] - La longitudine del tuo dispositivo\n[phonenr] - Numero dell\'ultima chiamata (entrante o uscente)\n[d] - Il giorno del mese, sempre 2 cifre\n[m] - Mese in formato numerico, sempre 2 cifre\n[Y] - L\anno, sempre 4 cifre\n[h] - Ore in formato 12 ore, sempre 2 cifre con due punti\n[H] - Ore in formato 24 ore, sempre 2 cifre con due punti\n[i] - Minuti, sempre 2 cifre\n[s] - Secondi, sempre 2 cifre\n[ms] - millisecondi, sempre 3 cifre [notificationTitle] - titolo dell\'ultima notifica [notificationText] - testo dell\'ultima notifica</string>
<string name="urlLegend">Variabili:\n È possibile utilizzare le seguenti variabili. Quando attivate, saranno sostituite con il valore corrispondente sul tuo dispositivo. Includi le parentesi nel tuo testo.\n\n[uniqueid] - L\'ID unico del tuo dispositivo\n[serialnr] - Il numero di serie del tuo dispositivio (&lt; Android 9)\n[latitude] - La latitudine del tuo dispositivo\n[longitude] - La longitudine del tuo dispositivo\n[phonenr] - Numero dell\'ultima chiamata (entrante o uscente)\n[d] - Il giorno del mese, sempre 2 cifre con zero iniziale \n[m] - Mese in formato numerico, sempre 2 cifre con zero iniziale \n[Y] - L\anno, sempre con 4 cifre\n[h] - Ore in formato 12 ore, sempre 2 cifre con due punti\n[H] - Ore in formato 24 ore, sempre 2 cifre con due punti\n[i] - Minuti, sempre 2 cifre\n[s] - Secondi, sempre 2 cifre\n[ms] - millisecondi, sempre 3 cifre\n[notificationTitle] - titolo dell\'ultima notifica\n[notificationText] - testo dell\'ultima notifica</string>
<string name="urlToTrigger">URL da caricare:</string>
<string name="urlTooShort">L\'url deve avere almeno 10 caratteri.</string>
<string name="usbTetheringFailForAboveGingerbread">Questo molto probabilmente non funzionerà dato che sei su una versione superiore ad Android 2.3. Tuttavia è possibile utilizzare la connessione wifi tethering per attivare la regola.</string>
@ -647,7 +647,7 @@
<string name="checkSettings">Controlla le impostazioni</string>
<string name="profileActive">profilo %1$s è attivo</string>
<string name="profileNotActive">profilo %1$s non attivo</string>
<string name="ruleXIsUsingProfileY">Impossibile eliminare questo profilo. La regola %s$1 fa riferimento al profilo %s$2.</string>
<string name="ruleXIsUsingProfileY">Impossibile eliminare questo profilo. La regola %1$s fa riferimento al profilo %2$s.</string>
<string name="profileCouldNotBeDeleted">Impossibile eliminare il profilo.</string>
<string name="noRepetition">nessuna ripetizione</string>
<string name="usingAuthentication">utilizzo dell\'autenticazione</string>
@ -659,4 +659,68 @@
<string name="pickActivityManually">Scegli manualmente</string>
<string name="launcherOrManualExplanation">Modalità semplice: l\'automazione può provare a identificare l\'attività di avvio del programma desiderato.\nIn alternativa puoi anche scegliere manualmente una delle attività dell\'applicazione.\nCosa vorresti?</string>
<string name="launcherNotFound">Impossibile identificare un\'attività di avvio di questa app. Dovrai sceglierne uno manualmente.</string>
<string name="createNotification">Crea notifica</string>
<string name="enterTitle">Inserisci un titolo.</string>
<string name="enterText">Aggiungi un testo.</string>
<string name="info">Informazioni</string>
<string name="profileWasNotFound">Il profilo utilizzato in questa regola non sembra più esistere. Il primo in ordine alfabetico è stato selezionato.</string>
<string name="comparisonCaseInsensitive">I confronti non distinguono fra maiuscole e minuscole</string>
<string name="closeNotifications">Chiudi notifica(e)</string>
<string name="notificationCloseActionExplanation">Se non specifichi alcun criterio, questa azione chiuderà TUTTE le notifiche. Quindi si consiglia di specificare almeno i criteri per almeno una applicazione, titolo o testo.</string>
<string name="profileWarning">Le impostazioni che modifichi in questa sezione possono far sì che tu non possa più notare certe cose dal tuo telefono. Possono perfino silenziare la sveglia. Quindi, qualunque cosa tu faccia, ti consigliamo di provarlo.</string>
<string name="ifString">se</string>
<string name="actionMediaControlNotice">Tieni presente che questa azione potrebbe non funzionare con TUTTI i lettori là fuori. E anche se lo facesse, non tutti i pulsanti funzionerebbero necessariamente.</string>
<string name="pleaseSelectActionValue">Si prega di selezionare un\'azione!</string>
<string name="stop">stop</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Controllo riproduzione multimediale</string>
<string name="next">prossimo</string>
<string name="previous">precedente</string>
<string name="pause">pausa</string>
<string name="play">riproduci</string>
<string name="playPause">attiva/disattiva riproduzione/pausa</string>
<string name="selectCommand">Seleziona comando</string>
<string name="actionMediaControl">Controllare la riproduzione multimediale</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">A causa della saggezza infinita di Google, l\'ultima versione di Android su cui questa funzione è nota per funzionare è %1 $s. Puoi configurarlo, ma probabilmente non avrà alcun effetto.</string>
<string name="screenState">Stato dello schermo</string>
<string name="selectDesiredState">Seleziona lo stato desiderato</string>
<string name="unlocked">Sbloccato</string>
<string name="off">spento</string>
<string name="on">attivo</string>
<string name="screenIs">lo schermo è %1$s</string>
<string name="sendEmailToDev">Invia email allo sviluppatore</string>
<string name="controlCenter">Centro di controllo</string>
<string name="emailContactNotice">L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.</string>
<string name="musicPlaying">La musica è in riproduzione</string>
<string name="musicIsPlaying">la musica è in riproduzione</string>
<string name="musicIsNotPlaying">la musica non viene riprodotta</string>
<string name="selectParameters">Selezionare i parametri</string>
<string name="musicCheckFrequencyTitle">Frequenza dei controlli [ms]</string>
<string name="musicCheckFrequencySummary">Millisecondi tra i controlli</string>
<string name="musicPlayingDetection">Rilevamento della riproduzione musicale</string>
<string name="profileXrequiresThis">Questo è richiesto dal profilo \"%1$s\".</string>
<string name="locationNotWorkingOn12">Ottenere la posizione non sembra funzionare su dispositivi Android 12 al momento. Se non funziona per te, mi dispiace. Cercherò di risolvere questo problema non appena conoscerò la causa. Quindi, se cerchio rotante non smette di girare, sai perché.</string>
<string name="lastProfile">Ultimo profilo:</string>
<string name="queryAllPackages">Ottenere un elenco delle applicazioni installate</string>
<string name="timeFrameDaysHint">Se si utilizza un intervallo di tempo che si estende oltre la mezzanotte, è necessario selezionare anche il giorno successivo se si desidera che il trigger venga applicato dopo la mezzanotte.</string>
<string name="featureNotInGooglePlayVersion">Questa funzione non è più disponibile nella versione di Google Play.\\n\\nOltre di tanto in tanto Google bullizza gli sviluppatori. Se si desidera continuare a utilizzare determinate funzionalità, è necessario archiviare i documenti. Sfortunatamente c\'è una probabilità del 99% che i documenti vengano rifiutati. È più o meno come nel fumetto / film di Asterix.\\n\\nHo passato settimane a discutere con loro su casi del genere in passato, ma ho continuato a ricevere rifiuti - sia da bot che da persone che sono intelligenti come i bot. Nella sezione Posso decidere se l\'app viene rimossa completamente dal Play Store o rimuovere la funzione.\\nConsigliare l\'utilizzo della versione APK dal mio sito Web o quella di F-Droid se sono necessarie tali funzionalità.</string>
<string name="startActivityInsertManually">Questa limitazione riguarda solo la selezione di un\'app, non l\'avvio effettivo. Quindi puoi comunque inserire manualmente il nome di un\'applicazione se lo conosci.</string>
<string name="deviceStarts">Device starts</string>
<string name="serviceStarts">Avvio del servizio</string>
<string name="deviceHasJustStarted">Il dispositivo è appena stato avviato</string>
<string name="serviceHasJustStarted">il servizio è appena iniziato</string>
<string name="broadcastReceived">broadcast non ricevuta</string>
<string name="broadcastNotReceived">broadcast ricevuta</string>
<string name="broadcastReceivedTitle">Broadcast ricevuta</string>
<string name="broadcastsShowSuggestions">Mostra suggerimenti</string>
<string name="selectBroadcast">Seleziona trasmissione</string>
<string name="lockedWithoutSecurity">bloccato (solo scorrimento rapido, nessun PIN)</string>
<string name="lockedWithSecurity">bloccato (con PIN, ecc.)</string>
<string name="lockedCommentScreenMustBeOff">Qualsiasi stato di blocco verrà rilevato solo se lo schermo è spento.</string>
<string name="emailPretext">Se hai un problema, suggerimenti o domande, scrivi qualcosa nell\'e-mail. Non inviarmi semplicemente i file con il corpo di posta predefinito. Ignorerò tutto ciò che li riguarda a meno che non siamo già in una conversazione.</string>
<string name="broadcastExplanation">Questa azione consente di inviare una trasmissione tramite il sistema di messaggi di Android. Questo non è visibile all\'utente, ma le applicazioni che si sono registrate per determinate trasmissioni possono rispondere ad esso.</string>
<string name="sendBroadcast">Invia broadcast</string>
<string name="enterBroadcast">Immettere un\'azione di broadcast.</string>
<string name="explanationBroadcastTrigger">La maggior parte degli eventi sul telefono verrà \"pubblicata\" trasmettendoli in tutto il sistema operativo.\nAd esempio, l\'attivazione/disattivazione della modalità aereo attiverà tale trasmissione. Queste trasmissioni non sono automaticamente visibili / udibili, ma se un\'applicazione (come l\'automazione) è interessata può collegarsi a loro. Quando si verificano, riceverà una notifica e può reagire.\n\nÈ possibile definire qui un evento di trasmissione per il quale l\'applicazione attenderà. Puoi inserirlo manualmente, copiarlo e incollarlo da qualche parte o sceglierne uno dall\'elenco dei suggerimenti. Poiché questo trigger è pensato per essere e rimanere molto flessibile, non posso fornirti spiegazioni per gli articoli.\n\nL\'elenco dei suggerimenti non pretende di essere completo. Si prega di visitare l\'URL sottostante per dare un\'occhiata alla documentazione Android.\nAnche qualsiasi app può inviare eventi personalizzati che ovviamente non appariranno nella documentazione Android.\n\nMolte trasmissioni richiedono autorizzazioni specifiche per funzionare. Provo a richiedere le autorizzazioni dove so che saranno richieste. Se ritieni che sia necessaria un\'autorizzazione per l\'azione che hai inserito, fammi sapere.\n\nNon ricevuto significa che non c\'è stata una trasmissione di questo tipo da quando il servizio è stato avviato. La risposta a determinati parametri è in fase di sviluppo.</string>
<string name="logsExplanation">Per evitare di utilizzare inutilmente lo spazio di archiviazione, i registri non vengono salvati per impostazione predefinita. Quindi, se hai un problema, attiva prima le impostazioni di accesso e imposta il livello di registro su 5. Quindi riprodurre il problema. Solo allora i registri possono essere allegati.</string>
<string name="directionStringDoesNotContain">non contiene</string>
</resources>

View File

@ -56,7 +56,7 @@
<string name="end">Einde</string>
<string name="save">Opslaan</string>
<string name="urlToTrigger">URL om te activeren:</string>
<string name="urlLegend">Variabelen:U kunt de volgende variabelen gebruiken. Bij het triggeren zullen ze worden vervangen door de corresponderende waarde op je apparaat. Zet de haakjes in uw tekst. \n[uniqueid] - Het unieke id van uw apparaat[serienummer] - Het serienummer van uw apparaat[latitude] - De breedtegraad van uw apparaat[longitude] - De lengtegraad van uw apparaat[phonenr] - Nummer van het laatste inkomende of uitgaande gesprek[d] - Dag van de maand, 2 cijfers met voorloopnullen[m] - Numerieke weergave van een maand, met voorloopnullen[Y] - een volledige numerieke weergave van een jaar, 4 cijfers[h] - 12-uurs indeling van een uur, met voorloopnullen[H] - 24-uurs indeling van een uur, met voorloopnullen[i] - minuten, met voorloopnullen[s] - seconden, met voorloopnullen[ms] - milliseconden[notificationTitle] - titel van de laatste melding[notificationText] - tekst van de laatste melding</string>
<string name="urlLegend">Variabelen:U kunt de volgende variabelen gebruiken. Bij het triggeren zullen ze worden vervangen door de corresponderende waarde op je apparaat. Zet de haakjes in uw tekst. \n[uniqueid] - Het unieke id van uw apparaat[serialnr] - Het serienummer van uw apparaat (&lt; Android 9)[latitude] - De breedtegraad van uw apparaat[longitude] - De lengtegraad van uw apparaat[phonenr] - Nummer van het laatste inkomende of uitgaande gesprek[d] - Dag van de maand, 2 cijfers met voorloopnullen[m] - Numerieke weergave van een maand, met voorloopnullen[Y] - een volledige numerieke weergave van een jaar, 4 cijfers[h] - 12-uurs indeling van een uur, met voorloopnullen[H] - 24-uurs indeling van een uur, met voorloopnullen[i] - minuten, met voorloopnullen[s] - seconden, met voorloopnullen[ms] - milliseconden[notificationTitle] - titel van de laatste melding[notificationText] - tekst van de laatste melding</string>
<string name="wifi">wifi</string>
<string name="activating">Activeren</string>
<string name="deactivating">Deactiveren</string>
@ -401,7 +401,7 @@
<string name="startNewThreadForRuleExecution">Start nieuw process voor activatie regel.</string>
<string name="newThreadRules">Nieuw process</string>
<string name="showIcon">Pictogram tonen</string>
<string name="showIconWhenServiceIsRunning">Pictogram tonen als de service draait (verbergen werkt alleen onder Android 7)</string>
<string name="showIconWhenServiceIsRunning">Pictogram tonen als de service draait (verbergen werkt alleen onder Android 7). Als u een hogere versie gebruikt, gaat u naar systeeminstellingen, vervolgens automatisering, vervolgens meldingen en schakelt u de \"Service notification\" uit.</string>
<string name="ruleHistory">Regelgeschiedenis (meest recente eerst):</string>
<string name="someOptionsNotAvailableYet">Sommige opties zijn uitgeschakeld omdat ze nog niet gebruikt kunnen worden. Ze zullen in een latere programmaversie worden geïntroduceerd.</string>
<string name="lockSoundChanges">Geluidswijzigingen vergrendelen</string>
@ -530,7 +530,7 @@
<string name="selectSoundFile">Selecteer geluidsbestand</string>
<string name="fileDoesNotExist">Bestand bestaat niet.</string>
<string name="noFileManageInstalled">Geen bestandsmanager geïnstalleerd.</string>
<string name="shareConfigAndLogFilesWithDev">Deel config en log bestanden met ontwikkelaar (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Config en log vastmaken</string>
<string name="shareConfigAndLogExplanation">Dit zal een nieuwe email starten met uw configuratie en log bestanden als zip bestand bijgevoegd. Het zal niet automatisch verzonden worden, je moet nog steeds op "verzenden" drukken. U kunt ook de ontvanger veranderen in bijvoorbeeld uzelf.</string>
<string name="startAppChoiceNote">Hier heeft u 2 algemene opties:. Je kunt een programma starten door een activiteit te selecteren. Stel je dit voor als het voorselecteren van een specifiek scherm/venster van een applicatie. Onthoud dat dit niet altijd zal werken. Dit komt omdat de vensters van een toepassing met elkaar kunnen interageren, bv. parameters doorgeven. Bij het botweg starten van een specifiek scherm heeft die interactie niet plaatsgevonden en kan het venster direct sluiten (waardoor het nooit echt getoond wordt). Probeer het desondanks! Je kunt een activiteitspad handmatig invoeren, maar het is aan te bevelen om de knop "Kiezen" te gebruiken. Als u besluit het pad handmatig in te voeren, voer dan in het bovenste veld de pakketnaam van de toepassing in en in het onderste veld het volledige pad van de activiteit.. Selectie door actie In tegenstelling tot het selecteren van een specifiek venster kunt u een programma ook door een actie starten. Dit is hetzelfde als roepen "Ik zou graag xyz willen" en als er een programma is geïnstalleerd dat u daarbij kan helpen, wordt het gestart. Een goed voorbeeld zou kunnen zijn start browser - je kunt er zelfs meerdere geïnstalleerd hebben (een is meestal de standaard). U moet dit handmatig invoeren, PackageName is hier optioneel. Houd in gedachten dat er geen variabelen zullen worden opgelost. Als je bijvoorbeeld de camera wilt starten met "MediaStore.ACTION_IMAGE_CAPTURE" zal dat niet werken. U moet een kijkje nemen in de Android documentatie en in plaats daarvan de werkelijke waarde van deze variabele gebruiken, die in dit voorbeeld zou zijn: "android.media.action.IMAGE_CAPTURE"</string>
<string name="errorRunningRule">Er is een fout opgetreden bij het uitvoeren van een regel.</string>
@ -543,7 +543,7 @@
<string name="enterValidAction">Voer een geldige actie in</string>
<string name="enterPackageName">Voer een geldige pakketnaam in.</string>
<string name="state">Staat</string>
<string name="phoneNumberExplanation">U kunt een specifiek telefoonnummer opgeven, maar dat hoeft niet. Als u er een wilt opgeven, kunt u er een uit uw adresboek kiezen of het handmatig invoeren. Daarnaast kun je reguliere expressies gebruiken. Om een reguliere expressie te testen is deze pagina behulpzaam:</string>
<string name="phoneNumberExplanation">U kunt een specifiek telefoonnummer opgeven (van de bellende partner), maar dat hoeft niet. Als u er een wilt opgeven, kunt u er een uit uw adresboek kiezen of het handmatig invoeren. Daarnaast kun je reguliere expressies gebruiken. Om een reguliere expressie te testen is deze pagina behulpzaam:</string>
<string name="importConfiguration">Import configuration</string>
<string name="exportConfiguration">Export configuration</string>
<string name="moreSettings">Meer instellingen</string>
@ -645,7 +645,7 @@
<string name="profileActive">profile %1$s is actief</string>
<string name="profileNotActive">profile %1$s is niet actief</string>
<string name="profileTriggerCheckSettings">Als dit selectievakje niet is uitgeschakeld, wordt het alleen aangevinkt als het geselecteerde profiel het laatste is dat is geactiveerd. Het maakt niet uit of audiogerelateerde instellingen extern zijn gewijzigd.\nAls het selectievakje echter is ingeschakeld, moeten de huidige audio-instellingen echt worden gedefinieerd in het profiel. PAS OP: Het controleren van het beltoonbestand wordt momenteel nog niet ondersteund.</string>
<string name="ruleXIsUsingProfileY">Kan dit profiel niet verwijderen. Regel %s$1 verwijst naar het profiel %s$2.</string>
<string name="ruleXIsUsingProfileY">Kan dit profiel niet verwijderen. Regel %1$s verwijst naar het profiel %2$s.</string>
<string name="profileCouldNotBeDeleted">Profiel kan niet worden verwijderd.</string>
<string name="noRepetition">geen herhaling</string>
<string name="usingAuthentication">authenticatie gebruiken</string>
@ -657,4 +657,68 @@
<string name="pickActivityManually">Handmatig kiezen</string>
<string name="launcherNotFound">Een launcher-activiteit van deze app kon niet worden geïdentificeerd. U moet er handmatig een kiezen.</string>
<string name="launcherOrManualExplanation">Eenvoudige modus: Automatisering kan proberen de opstartactiviteit van het gewenste programma te identificeren.\nU kunt ook handmatig een van de activiteiten van de toepassing kiezen.\nWat wil je?</string>
<string name="info">Info</string>
<string name="profileWasNotFound">Het profiel dat in deze regel wordt gebruikt, lijkt niet meer te bestaan. De alfabetisch eerste is geselecteerd.</string>
<string name="enterText">Voer een tekst in.</string>
<string name="enterTitle">Voer een titel in.</string>
<string name="createNotification">Melding maken</string>
<string name="notificationCloseActionExplanation">Als u geen criteria opgeeft, worden met deze actie ALLE meldingen gesloten. Het is dus aan te raden om in ieder geval criteria te specificeren voor minimaal 1 van de toepassing, titel of tekst.</string>
<string name="closeNotifications">Melding(en) sluiten</string>
<string name="comparisonCaseInsensitive">Vergelijkingen worden gedaan case-INsensitief</string>
<string name="profileWarning">De instellingen die je hier maakt kunnen ervoor zorgen dat je bepaalde dingen niet meer van je telefoon merkt. Ze kunnen zelfs je wekker dempen. Dus wat je ook doet - het wordt aanbevolen om het te testen.</string>
<string name="ifString">als</string>
<string name="emailContactNotice">E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.</string>
<string name="controlCenter">Controlecentrum</string>
<string name="sendEmailToDev">Stuur een e-mail naar de ontwikkelaar</string>
<string name="screenIs">scherm is %1$s</string>
<string name="on">op</string>
<string name="off">af</string>
<string name="unlocked">ontgrendeld</string>
<string name="selectDesiredState">Selecteer de gewenste status</string>
<string name="screenState">Schermstatus</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Vanwege de oneindige wijsheid van Google is de laatste Android-versie waarvan bekend is dat deze functie werkt% 1 $ s. U kunt het configureren, maar het zal waarschijnlijk geen effect hebben.</string>
<string name="actionMediaControl">Het afspelen van media regelen</string>
<string name="selectCommand">Opdracht Selecteren</string>
<string name="playPause">schakelaar afspelen/pauzeren</string>
<string name="play">afspelen</string>
<string name="pause">pauzeren</string>
<string name="previous">vorig</string>
<string name="next">volgend</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Het afspelen van media regelen</string>
<string name="stop">stoppen</string>
<string name="pleaseSelectActionValue">Selecteer een actie!</string>
<string name="actionMediaControlNotice">Houd er rekening mee dat deze actie mogelijk niet werkt met ALLE spelers die er zijn. En zelfs als dat zo is, werkt niet elke knop noodzakelijkerwijs.</string>
<string name="musicPlaying">Er wordt muziek afgespeeld</string>
<string name="selectParameters">Selecteer parameters</string>
<string name="musicIsPlaying">er wordt muziek afgespeeld</string>
<string name="musicIsNotPlaying">muziek wordt niet afgespeeld</string>
<string name="musicCheckFrequencyTitle">Controleer frequentie [ms]</string>
<string name="musicCheckFrequencySummary">Milliseconden tussen controles</string>
<string name="musicPlayingDetection">Detectie van het afspelen van muziek</string>
<string name="locationNotWorkingOn12">Het verkrijgen van de locatie lijkt momenteel niet te werken op Android 12-apparaten. Als het niet voor je werkt, spijt het me. Ik zal proberen dit op te lossen zodra ik de oorzaak ken. Dus als de donut niet stopt met draaien, weet je waarom.</string>
<string name="profileXrequiresThis">Profiel \"%1$s\" vereist dit.</string>
<string name="lastProfile">Laatste profiel:</string>
<string name="queryAllPackages">Een lijst met geïnstalleerde toepassingen ophalen</string>
<string name="timeFrameDaysHint">Als u een tijdsbestek gebruikt dat zich uitstrekt over middernacht, moet u ook de volgende dag selecteren als u wilt dat de trigger na middernacht van toepassing is.</string>
<string name="featureNotInGooglePlayVersion">Deze functie is niet meer beschikbaar in de Google Play-versie.\\n\\nAlles af en toe pest Google ontwikkelaars. Als u bepaalde functies wilt blijven gebruiken, moet u papierwerk indienen. Helaas is er een kans van 99% dat het papierwerk wordt afgewezen. Het is vrijwel net als in de Asterix-strip / film.\\n\\nIk heb in het verleden wekenlang met hen gediscussieerd over dergelijke gevallen, maar ik bleef afwijzingen krijgen - hetzij door bots of mensen die ongeveer net zo intelligent zijn als bots. In de ik kan kiezen tussen de app die volledig uit de Play Store wordt verwijderd of de functie verwijdert.\\n Overweeg de APK-versie van mijn website of die van F-Droid te gebruiken als je die functies nodig hebt.</string>
<string name="startActivityInsertManually">Deze beperking heeft alleen betrekking op de selectie van een app, niet op de daadwerkelijke start. U kunt dus nog steeds handmatig de naam van een toepassing invoeren als u deze kent.</string>
<string name="deviceHasJustStarted">apparaat is net gestart</string>
<string name="serviceHasJustStarted">service is net begonnen</string>
<string name="serviceStarts">Service start</string>
<string name="deviceStarts">Apparaat start</string>
<string name="emailPretext">Als je een probleem, suggesties of vraag hebt, schrijf dan iets in de e-mail. Stuur me niet alleen de bestanden met de standaard e-mailtekst. Ik zal alles negeren, tenzij we al in gesprek zijn.</string>
<string name="lockedCommentScreenMustBeOff">Elke vergrendelde status wordt alleen gedetecteerd als het scherm is uitgeschakeld.</string>
<string name="lockedWithSecurity">vergrendeld (met PINCODE, enz.)</string>
<string name="lockedWithoutSecurity">vergrendeld (alleen vegen, geen pincode)</string>
<string name="selectBroadcast">Selecteer broadcast</string>
<string name="broadcastsShowSuggestions">Toon suggesties</string>
<string name="broadcastReceivedTitle">Broadcast ontvangen</string>
<string name="broadcastNotReceived">broadcast niet ontvangen</string>
<string name="broadcastReceived">broadcast ontvangen</string>
<string name="broadcastExplanation">Deze actie maakt het mogelijk om een uitzending te versturen via het berichtensysteem van Android. Dit is niet zichtbaar voor de gebruiker, maar applicaties die zich voor bepaalde uitzendingen hebben geregistreerd, kunnen hierop reageren.</string>
<string name="sendBroadcast">Broadcast verzenden</string>
<string name="enterBroadcast">Voer een uitzendactie in.</string>
<string name="explanationBroadcastTrigger">De meeste gebeurtenissen op uw telefoon worden \"gepubliceerd\" door ze uit te zenden in het hele besturingssysteem.\nHet in- en uitschakelen van de vliegtuigmodus zal bijvoorbeeld een dergelijke uitzending activeren. Die uitzendingen zijn niet automatisch zichtbaar/hoorbaar, maar als een applicatie (zoals Automation) geïnteresseerd is, kan deze erop aansluiten. Wanneer ze zich voordoen, wordt het een melding gegeven en kan het reageren.\n\nU kunt hier een uitzendgebeurtenis definiëren waarop de toepassing zal wachten. U kunt het handmatig invoeren, ergens vandaan kopiëren en plakken of er een kiezen uit de lijst met suggesties. Omdat deze trigger bedoeld is en zeer flexibel is, kan ik u geen uitleg geven voor de items.\n\nDe lijst met suggesties beweert niet volledig te zijn. Ga naar de onderstaande URL om de Android-documentatie te bekijken.\nOok kan elke app aangepaste gebeurtenissen verzenden die natuurlijk niet in de Android-documentatie worden weergegeven.\n\nVeel uitzendingen vereisen specifieke machtigingen om te kunnen werken. Ik probeer toestemmingen te vragen waarvan ik weet dat ze nodig zijn. Als u denkt dat er een toestemming vereist is voor de actie die u hebt ingevoerd, laat het me dan weten.\n\nNiet ontvangen betekent dat er sinds de service is gestart niet meer zo\'n uitzending is geweest. Inspelen op bepaalde parameters is in ontwikkeling.</string>
<string name="logsExplanation">Om onnodige slijtage van uw opslag te voorkomen, worden logboeken niet standaard opgeslagen. Dus als u een probleem hebt, activeer dan eerst de inloginstellingen en stel het logniveau in op 5. Reproduceer vervolgens het probleem. Alleen dan kunnen logs worden bijgevoegd.</string>
<string name="directionStringDoesNotContain">bevat geen</string>
</resources>

View File

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

View File

@ -70,7 +70,7 @@
<string name="end">End</string>
<string name="save">Save</string>
<string name="urlToTrigger">URL to trigger:</string>
<string name="urlLegend">Variables:\nYou can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text.\n\n[uniqueid] - Your device\'s unique id\n[serialnr] - Your device\'s serial number\n[latitude] - Your device\'s latitude\n[longitude] - Your device\'s longitude\n[phonenr] - Number of last incoming or outgoing call\n[d] - Day of the month, 2 digits with leading zeros\n[m] - Numeric representation of a month, with leading zeros\n[Y] - A full numeric representation of a year, 4 digits\n[h] - 12-hour format of an hour with leading zeros\n[H] - 24-hour format of an hour with leading zeros\n[i] - Minutes with leading zeros\n[s] - Seconds, with leading zeros\n[ms] - milliseconds\n[notificationTitle] - title of last notification\n[notificationText] - text of last notification</string>
<string name="urlLegend">Variables:\nYou can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text.\n\n[uniqueid] - Your device\'s unique id\n[serialnr] - Your device\'s serial number (&lt; Android 9)\n[latitude] - Your device\'s latitude\n[longitude] - Your device\'s longitude\n[phonenr] - Number of last incoming or outgoing call\n[d] - Day of the month, 2 digits with leading zeros\n[m] - Numeric representation of a month, with leading zeros\n[Y] - A full numeric representation of a year, 4 digits\n[h] - 12-hour format of an hour with leading zeros\n[H] - 24-hour format of an hour with leading zeros\n[i] - Minutes with leading zeros\n[s] - Seconds, with leading zeros\n[ms] - milliseconds\n[notificationTitle] - title of last notification\n[notificationText] - text of last notification</string>
<string name="wifi">wifi</string>
<string name="activating">Activating</string>
<string name="deactivating">Deactivating</string>
@ -496,7 +496,7 @@
<string name="startNewThreadForRuleExecution">Start new thread for rule activation.</string>
<string name="newThreadRules">New thread</string>
<string name="showIcon">Show icon</string>
<string name="showIconWhenServiceIsRunning">Show icon when service is running (hiding it only works below Android 7)</string>
<string name="showIconWhenServiceIsRunning">Show icon when service is running (hiding it only works below Android 7). If you\'re on a higher version, go to system settings, then Automation, then notifications and disable the \"Service notification\".</string>
<string name="ruleHistory">Rule history (most recent first):</string>
<string name="someOptionsNotAvailableYet">Some options are disabled as they cannot be used, yet. They will be introduced in a later program version.</string>
<string name="lockSoundChanges">Lock sound changes</string>
@ -567,6 +567,7 @@
<string name="android.permission.ACCESS_NOTIFICATION_POLICY">Override do not disturb policy</string>
<string name="theseAreThePermissionsRequired">These are the permissions required:</string>
<string name="ruleXrequiresThis">Rule \"%1$s\" requires this.</string>
<string name="profileXrequiresThis">Profile \"%1$s\" requires this.</string>
<string name="helpTextActivityDetection">This feature can detect if you\'re currently on the go and if it is on foot or in which type of vehicle (to a certain extent). The feature is not fully built into Automation, but is provided by Google Play Services. Technically it does not give a yes/no result, but return a percentage to which level it is sure it detected you\'re status. You can setup the percentage value from which Automation will accept a result. Two remarks: 1) More than 1 status could occur at the same time. For example you might be WALKING inside a driving bus. 2) This sensor is relatively expensive in terms of battery usage. If it is possible you might consider using alternatives, e.g. require your car\'s handsfree device to be connected to detect you\'re driving.</string>
<string name="sendTextMessage">Send text message</string>
<string name="textToSend">Text to send</string>
@ -631,7 +632,7 @@
<string name="selectSoundFile">Select sound file</string>
<string name="fileDoesNotExist">File does not exist.</string>
<string name="noFileManageInstalled">No file manager installed.</string>
<string name="shareConfigAndLogFilesWithDev">Share config and log files with developer (via email).</string>
<string name="shareConfigAndLogFilesWithDev">Attach config and log files.</string>
<string name="shareConfigAndLogExplanation">This will start a new email with your config and log files attached as zip file. It will not be sent automatically, you still need to hit \"send\". You can also change the recipient to yourself for example.</string>
<string name="startAppChoiceNote">Here you have 2 general options:\n\n1. You can start a program by selecting an activity. Imagine this like preselecting a specific screen/window of an application. Keep in mind this may not always work. This is because the windows of an app might interact with each other, e.g. pass on parameters. When bluntly starting a specific screen that interaction has not happened and the window might close instantly (therefore it\'s never really shown). Try it nevertheless! You can enter an activity path manually, but it\'s recommended to use the \"Select\" button. If you decide to enter it manually enter the app\'s package name in the upper field and the full path of the activity in the lower one.\n\n2. Selection by action In contrast to selecting a specific window you can also start a program by an action. This is like shouting out \"I\'d would like xyz\" and if there\'s an app installed that can help you with that it will be started. A good example would be start browser - you might even have multiple installed (one is usually the default one). You need to enter this manually, PackageName is optional here. Keep in mind no variables will be resolved. If you want to start the camera for example using \"MediaStore.ACTION_IMAGE_CAPTURE\" will not work. You have to take a look at the Android documentation and use this variable\'s actual value instead which in this example would be \"android.media.action.IMAGE_CAPTURE\".</string>
<string name="errorRunningRule">There was an error running a rule.</string>
@ -644,7 +645,7 @@
<string name="enterValidAction">Enter a valid action</string>
<string name="enterPackageName">Enter a valid package name.</string>
<string name="state">State</string>
<string name="phoneNumberExplanation">You can enter a specific phone number, but you don\'t have to. If you want to specify one you can either pick one from your address book or enter it manually. In addition you may use regular expressions. To test a regular expression I like this page:</string>
<string name="phoneNumberExplanation">You can enter a specific remote phone number, but you don\'t have to. If you want to specify one you can either pick one from your address book or enter it manually. In addition you may use regular expressions. To test a regular expression I like this page:</string>
<string name="importConfiguration">Import configuration</string>
<string name="exportConfiguration">Export configuration</string>
<string name="moreSettings">More settings</string>
@ -743,7 +744,7 @@
<string name="profileActive">profile %1$s is active</string>
<string name="profileNotActive">profile %1$s is not active</string>
<string name="profileTriggerCheckSettings">If this checkbox is not disabled, it will only be checked if the selected profile has been the last one to be activated. It doesn\'t matter if any audio related settings have been changed externally. However if the checkbox is enabled, the current audio settings really need to be like defined in the profile. BEWARE: Checking the ringtone file is currently not supported, yet.</string>
<string name="ruleXIsUsingProfileY">Cannot delete this profile. Rule %s$1 is referencing profile %s$2.</string>
<string name="ruleXIsUsingProfileY">Cannot delete this profile. Rule %1$s is referencing profile %2$s.</string>
<string name="profileCouldNotBeDeleted">Profile could not be deleted.</string>
<string name="noRepetition">no repetition</string>
<string name="usingAuthentication">using authentication</string>
@ -755,4 +756,82 @@
<string name="pickActivityManually">Choose manually</string>
<string name="launcherOrManualExplanation">Easy mode: Automation can try to identify the launcher activity of the desired program automatically. Alternatively you can also pick one of the application\'s activities manually. What would you like?</string>
<string name="launcherNotFound">A launcher activity of this app could not be identified. You will have to pick one manually.</string>
<string name="createNotification">Create notification</string>
<string name="enterTitle">Enter a title.</string>
<string name="enterText">Enter a text.</string>
<string name="info">Info</string>
<string name="profileWasNotFound">The profile used in this rule doesn\'t seem to exist anymore. The alphabetically first one has been selected.</string>
<string name="notificationCloseActionExplanation">If you don\'t specify any criteria this action will close ALL notifications. So it\'s advised to at least specify criteria for at least 1 of application, title or text.</string>
<string name="closeNotifications">Close notification(s)</string>
<string name="comparisonCaseInsensitive">Comparisons are done case-INsensitive</string>
<string name="profileWarning">The settings you can adjust here, can cause that you don\'t notice certain things from your phone anymore. They may even silence your wakeup alarm. So whatever you do - it is recommended you test it.</string>
<string name="ifString">if</string>
<string name="emailContactNotice">Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.</string>
<string name="controlCenter">Control center</string>
<string name="sendEmailToDev">Send email to developer</string>
<string name="screenIs">screen is %1$s</string>
<string name="on">on</string>
<string name="off">off</string>
<string name="unlocked">unlocked</string>
<string name="selectDesiredState">Select desired state</string>
<string name="screenState">Screen state</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Because of Google\'s infinite wisdom, the last Android version this feature is known to work on is %1$s. You can configure it, but it probably will not have any effect.</string>
<string name="actionMediaControl">Control media playback</string>
<string name="selectCommand">Select command</string>
<string name="playPause">toggle play/pause</string>
<string name="play">play</string>
<string name="pause">pause</string>
<string name="previous">previous</string>
<string name="next">next</string>
<string name="android.permission.MEDIA_CONTENT_CONTROL">Control media playback</string>
<string name="stop">stop</string>
<string name="pleaseSelectActionValue">Please select an action!</string>
<string name="actionMediaControlNotice">Keep in mind that this action may not work with ALL players out there. And even if it does, not every buttons does necessarily work.</string>
<string name="musicPlaying">Music playing</string>
<string name="selectParameters">Select parameters</string>
<string name="musicIsPlaying">music is playing</string>
<string name="musicIsNotPlaying">music is not playing</string>
<string name="musicPlayingDetection">Music playing detection</string>
<string name="musicCheckFrequencyTitle">Check frequency [ms]</string>
<string name="musicCheckFrequencySummary">Milliseconds between checks</string>
<string name="locationNotWorkingOn12">Getting the location does not seem to be working on Android 12 devices currently. If it isn\'t working for you, I\'m sorry. I\'ll try to fix this as soon as I know the cause. So if the donut doesn\'t stop spinning, you know why.</string>
<string name="lastProfile">Last profile:</string>
<string name="queryAllPackages">Get a list of installed applications</string>
<string name="timeFrameDaysHint">If you use a timeframe that stretches over midnight you need to select the following day as well if you want the trigger to apply after midnight.</string>
<string name="featureNotInGooglePlayVersion">This feature is not available in the Google Play version anymore.\n\nEvery now and then Google bullies developers. If you want to keep using certain features you have to file paperwork. Unfortunately there\'s a 99% chance that the paperwork gets rejected. It\'s pretty much like in the Asterix comic/movie.\n\nI\'ve spent weeks arguing with them about cases like that in the past, but I kept getting rejections - either by bots or people who are about as intelligent as bots. In the I can decide between the app being removed from the Play Store entirely or remove the feature.\nPlease consider using the APK version from my website or the one from F-Droid if you need those features.</string>
<string name="startActivityInsertManually">This limitation concerns only the selection of an app, not the actual start. So you can still enter the name of an application manually if you know it.</string>
<string name="deviceStarts">Device starts</string>
<string name="serviceStarts">Service starts</string>
<string name="deviceHasJustStarted">device has just started</string>
<string name="serviceHasJustStarted">service has just started</string>
<string name="broadcastReceived">broadcast received</string>
<string name="broadcastNotReceived">broadcast not received</string>
<string name="explanationBroadcastTrigger">Most events on your phone will be \"published\" by broadcasting them throughout the operating system.\nFor example turning on/off airplane mode will trigger such a broadcast. Those broadcasts are not automatically visible/audible, but if an application (like Automation) is interested it can hook up to them. When they occur it will get notified and can react.\n\nYou can define a broadcast event here for which the application will wait. You may enter it manually, copy &amp; paste it from somewhere or pick one from the list of suggestions. As this trigger is meant to be and remain very flexible I cannot provide you with explanations for the items.\n\nThe list of suggestions does not claim to be complete. Please visit the below URL to have a look at the Android documentation.\nAlso any app can send custom events which will not appear in the Android documentation of course.\n\nMany broadcasts require specific permissions in order to work. I try to request permissions where I know they will be required. If you think a permission is required for the action you entered, please let me know.\n\nNot received means there has not been such a broadcast ever since the service has been started. Responding to certain parameters is in development.</string>
<string name="broadcastListUrl" translatable="false">https://developer.android.com/reference/android/content/Intent.html</string>
<string name="broadcastReceivedTitle">Broadcast received</string>
<string name="logsExplanation">To avoid unnecessary wearing of your storage, logs are not saved by default. So if you have a problem please activate logging in settings first and set log level to 5. Then reproduce the problem. Only then logs can be attached.</string>
<string name="broadcastsShowSuggestions">Show suggestions</string>
<string name="selectBroadcast">Select broadcast</string>
<string name="lockedWithoutSecurity">locked (swipe only, no PIN)</string>
<string name="lockedWithSecurity">locked (with PIN, etc.)</string>
<string name="lockedCommentScreenMustBeOff">Any state of locked will only be detected if the screen is off.</string>
<string name="emailPretext">If you have a problem, suggestions or question, please write something in the email. Do not just send me the files with the default mail body. I will ignore everything those unless we\'re already in a conversation.</string>
<string name="sendBroadcast">Send broadcast</string>
<string name="enterBroadcast">Enter a broadcast action.</string>
<string name="broadcastExplanation">This action allows to send a broadcast across the Android OS messaging system. This is not user-visible, but apps who listen for that specific broadcast can respond to it being sent.</string>
<string name="directionStringDoesNotContain">does not contain</string>
<string name="runExecutable">Run script or executable</string>
<string name="path">Path</string>
<string name="parameters">Parameters</string>
<string name="chooseExecutable">Choose executable</string>
<string name="runAsRoot">Run as root</string>
<string name="selectValidExecutable">Select a valid executable file.</string>
<string name="fileNotExecutable">The file is not executable.</string>
<string name="wifiExplanation1">Apps targeting Android Q or higher cannot turn wifi on or off anymore. Please blame Google for this restriction, not me.\n\nYou can bypass this restriction by rooting your device and activating the checkbox below. Alternatively download this application from F-Droid or my website as I am not forced to target the latest API level in those versions.</string>
<string name="wifiExplanation2">While airplane mode is activated, wifi can only be toggled from applications when using root permissions for that.</string>
<string name="usingRoot">using root</string>
<string name="runExecutableExplanation">You can select a script or an executable file here that will be executed as an action.\n\nBut there are some prerequisites which you have to deal with on your own. Google has made it very hard to run anything other than regular Android applications.\n\n1.\nThe file must be marked as executable in the file system. On a regular Android system (without root) this is actually the hard part.\n\n2.\nThat also means Automation must be able to execute the file, not just the owner or the group.\n\n3.\nIf it is a script, a valid shell be specified in the script\'s header.</string>
<string name="tetheringActive">tethering is active</string>
<string name="tetheringNotActive">tethering is not active</string>
<string name="tetheringState">Tethering state</string>
</resources>

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,8 @@ Mögliche Auslöser:
* Telefongespräch im Gange
* Benachrichtigungen anderer Anwendungen
* Geräteausrichtung (Gyroskop)
* Profile aktiv oder nicht
* Broadcasts anderer Anwendungen
Mögliche Aktionen:
* WLAN ein-/ausschalten
@ -40,6 +42,7 @@ Mögliche Aktionen:
* Bildschirmhelligkeit ändern
* SMS verschicken
* Sounddatei abspielen.
* Benachrichtigungen erstellen
Es ist ziemlich schwierig diese Anwendung über die vielen verschiedenen Geräte und Android Versionen am Laufen zu halten. Ich kann vieles im Emulator testen, aber eben nicht alles.
Wenn also eine bestimmte Funktion nicht so tut wie sie sollte - lassen Sie es mich wissen. Über die Jahre habe ich noch alle Fehler behoben, die mir vernünftig gemeldet wurden. Aber dafür bin ich auf Ihre Mithilfe angewiesen.
@ -50,6 +53,9 @@ Wenn Sie ein Problem mit der Anwendung haben und mich dazu kontaktieren möchten
Spenden sind sicher eine gute, aber nicht die einzige Möglichkeit mich zu motivieren :-)
* Wer mir etwas Gutes tun will, kann die Anwendung auch im Play Store bewerten (https://play.google.com/store/apps/details?id=com.jens.automation2).
* Außerdem ist Hilfe bei der Übersetzung willkommen. Englisch, Spanisch und Deutsch kann ich selbst. Aber sonst ist alles gern gesehen.
* Wenn Ihnen die Anwendung gefällt, freue ich mich auch einfach nur über eine Email mit ein paar netten Worten.
* Außerdem ist immer Hilfe bei der Übersetzung willkommen. Englisch, Spanisch und Deutsch kann ich selbst, Italienisch ist bereits abgedeckt. Aber sonst ist alles gern gesehen.
* Wenn Sie ein Talent/Erfahrung auf dem Gebiet Grafikdesign haben und Ideen für hübschere Symbole haben, lassen Sie es mich wissen.
* Falls Sie einen interessanten Anwendungsfall haben oder einen Weg gefunden haben, Auslöser und Aktionen so zu kombinieren, um etwas Besonderes umzusetzen und Sie denken, daß man das auf die Beispielseite (https://server47.de/automation/examples.html) setzen sollte, kontaktieren Sie mich doch.
Erklärungen zu den vielen Berechtigungen können hier abgerufen werden: https://server47.de/automation/permissions_de.html
Erklärungen zu den vielen Berechtigungen können hier abgerufen werden: https://server47.de/automation/permissions.php

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

View File

@ -1 +1,11 @@
* New trigger: screen state (on/off)
* New action: Create notification
* New action: Close notification(s)
* New action: Control media playback
* Fixed: Translation bug in dutch variables text
* Fixed: Variables were not replaced when sending text messages
* Fixed: Service wouldn't always start after device has been powered on
* Fixed: Set ringtones on Android 11 and above
* Fixed: Permission read storage required for changing ringtones
* Fixed: Profile that were not in use, could not be deleted.
* Fixed: Orientation sensor on devices that have no magnetic sensor.

View File

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

View File

@ -0,0 +1,7 @@
* New trigger: device has just started
* New trigger: service has just started
* New trigger: Respond to customizable broadcasts
* New parameter for trigger Screen state: New state "locked"
* New action: Send broadcasts
* Fixed: Crash when editing notification trigger
* Fixed: TimeFrame trigger - time may have changed when crossing timezones

View File

@ -20,6 +20,8 @@ Supported triggers:
* Phone call running
* Notifications of other apps
* Device orientation (gyroscope)
* Profile active or not
* Broadcasts of other apps
Supported actions:
* Change wifi state
@ -40,6 +42,7 @@ Supported actions:
* Change screen brightness
* Send text message
* Play sound file
* Create notifications
It's quite hard to keep this app working across the many different hardwares as well as the many changes Android undergoes over the versions. I can test it in the emulator, but that cannot show all bugs.
So if a certain feature is not working on your device - let me know. Over the years I have fixed almost all bugs that have been reasonably reported to me. But for that I'm dependend on your input.
@ -50,6 +53,9 @@ If you have a problem and think about contacting me please
Donations are certainly a good, but not the only way to motivate me :-)
* If you'd like to support me, you can also leave a positive review for the app on Google Play (https://play.google.com/store/apps/details?id=com.jens.automation2).
* Furthermore I can always use help in translating the app. English, German and some Spanish are among my own skills. But everything else is more than welcome.
* If you like the app, simply some warm words via email are always appreciated.
* Furthermore I can always use help in translating the app. English, German and some Spanish are among my own skills. Italian is covered by somebody already. But everything else is more than welcome.
* If you have a talent/experience in graphics design and have some ideas for nicer icons let me know.
* If you have an interesting use-case or found a way to combine triggers and actions to achieve something intriguing and you think it's worth putting it on the examples page (https://server47.de/automation/examples.html), let me know.
Explanation of the many permissions can be found here: https://server47.de/automation/permissions_en.html
Explanation of the many permissions can be found here: https://server47.de/automation/permissions.php

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Some files were not shown because too many files have changed in this diff Show More