Compare commits

...

106 Commits

Author SHA1 Message Date
jens 7a9e03ed4d Removed redundant space character in notification 2026-06-11 16:51:57 +02:00
jens 887e6de3e4 Distinction between settings 2026-05-14 20:22:58 +02:00
jens 5417b4e739 Small bugfixes 2026-04-12 12:47:59 +02:00
jens 7e72dfd19a Version 1.8.7 2026-03-06 22:22:34 +01:00
jens 23223480e5 Version 1.8.6 2026-03-06 22:05:01 +01:00
jens e3e2a87b5e Http request action streamlined to also cover the insecure setting in the same function. 2026-03-01 00:20:53 +01:00
jens 4cea4391eb Libraries updated 2026-02-28 22:52:42 +01:00
jens 63150ed8f6 Libraries updated 2026-02-27 23:56:04 +01:00
jens d986fcdf4d Upgraded to Gradle 8.13.2 2026-02-27 23:09:30 +01:00
jens ea57dd01e5 Upgraded to Gradle 8.4.2 2026-02-27 23:07:22 +01:00
jens 6f1f112d98 Further actions for trigger url action 2026-02-27 22:46:31 +01:00
jens 549c4f109e Merge remote-tracking branch 'origin/development' into development 2026-02-25 23:02:02 +01:00
jens d63841dd27 Further actions for trigger url action 2026-02-25 23:01:45 +01:00
jens 4913f9236b Version 1.8.5 2026-02-01 18:28:20 +01:00
jens 8f6e376231 Version 1.8.5 2026-02-01 18:12:37 +01:00
jens 9ff121e82a URL in variable bug fixed 2026-01-25 18:55:44 +01:00
jens ccf87dbef0 Action to change system settings 2026-01-06 16:51:13 +01:00
jens b510811b18 Action to change system settings 2026-01-05 18:00:46 +01:00
jens c1619e67ec Action to change system settings 2026-01-02 17:15:25 +01:00
jens 1c22a3386b Action to change system settings 2026-01-01 17:17:58 +01:00
jens b83b6568ca Minor changes 2025-12-31 15:54:25 +01:00
jens 4a90b36f6a Many small fixes 2025-12-28 15:27:50 +01:00
jens fd90b14bdc Release candidate 2025-12-26 16:06:09 +01:00
jens 91fdef99c3 startActivity package name fix 2025-12-17 23:22:14 +01:00
jens 63264fcf9b Profile activation logs 2025-12-14 12:49:58 +01:00
jens 2758ef180d NFC tag fix 2025-12-07 23:13:15 +01:00
jens 3d2b48706d Vibrations fix 2025-12-07 14:00:17 +01:00
jens e52ce4cd30 Crash in Google Play version fixed 2025-12-07 12:53:48 +01:00
jens bbb477fc77 Merge branch 'development' of https://git.server47.de/jens/Automation into development
# Conflicts:
#	fastlane/metadata/android/en-US/changelogs/145.txt
2025-12-06 18:00:53 +01:00
jens 4478006109 Permission check for ability to schedule exact timers 2025-12-06 17:59:22 +01:00
jens d117484143 Variable comparison check fixed 2025-12-06 11:30:58 +01:00
jens f7d8389668 Trigger URL fixes 2025-11-29 23:41:32 +01:00
jens 4282c53372 Vibration fix 2025-11-23 18:47:38 +01:00
jens 35e2a1158d Fixed airplane mode trigger not working 2025-11-16 20:30:38 +01:00
jens 66e86e66b3 Minor corrections 2025-11-13 23:12:17 +01:00
jens 4c4a355ff5 BLUETOOTH_CONNECT permission requested for Bluetooth trigger editor in Google Play version 2025-11-10 23:51:13 +01:00
jens 07011b2053 proximity trigger 2025-11-09 23:11:28 +01:00
jens fdcdaf53c9 proximity trigger 2025-11-06 23:27:32 +01:00
jens 55a1c24753 proximity trigger 2025-11-06 22:35:49 +01:00
jens ca88fbfb07 proximity trigger 2025-11-02 23:56:58 +01:00
jens 3497d7b8ea Proximity sensor trigger 2025-11-02 19:10:05 +01:00
jens e8e763210b trigger_url variable name fixed 2025-11-02 01:02:41 +01:00
jens b6ea652e46 UI theme can be changed 2025-10-29 23:24:13 +01:00
jens a30a47f67a UI theme can be changed 2025-10-27 00:13:08 +01:00
jens 914f5c033b UI theme 2025-10-26 19:35:14 +01:00
jens f64b8ea860 Missing translation added 2025-10-26 18:38:18 +01:00
jens 2445431393 Missing translation added 2025-10-25 00:34:47 +02:00
jens a6e10d09c3 Forum added to contact options 2025-10-19 23:32:34 +02:00
jens 7972a335c3 Foreground service type 2025-10-18 18:03:53 +02:00
jens e99203c7e4 Multiple bug fixes 2025-07-19 23:21:44 +02:00
jens ee311b0ba5 New version 1.8.3 RC 2025-07-19 18:03:37 +02:00
jens fb64c46c95 Many fixes 2025-07-18 19:05:42 +02:00
jens c7557519e8 Many fixes 2025-07-16 18:08:58 +02:00
jens 01c1ac3f5e Many fixes 2025-07-15 16:46:03 +02:00
jens b473034703 Many fixes 2025-07-12 18:51:37 +02:00
jens bf78ecc794 Many fixes 2025-07-10 18:39:07 +02:00
jens 6d9a77a990 Screen brightness 2025-07-09 21:20:21 +02:00
jens ec68d375c7 Many fixes 2025-07-08 18:11:56 +02:00
jens e8524f719f Fixed warnings in logs for formatted notifications 2025-05-01 16:07:22 +02:00
jens f04c517c80 Toggle logcat on/off 2025-04-27 13:32:30 +02:00
jens b6d7958389 Invert variable check 2025-03-30 17:50:39 +02:00
jens 04d2e4b432 Bugfix when checking for any battery charging type 2025-03-23 18:33:13 +01:00
jens abd346946a Bugfix when triggering URL 2025-03-22 20:27:59 +01:00
jens 17edf90086 v1.8.2 2025-01-19 16:03:10 +01:00
jens 879e1c6ef3 Additional variables 2024-12-27 15:10:29 +01:00
jens d7d806fb5c Added permission for Termux remote commands 2024-08-25 17:11:24 +02:00
jens 910af92989 Multiple bug fixes 2024-08-11 14:58:13 +02:00
jens 9f36411511 New version 2024-05-23 23:03:43 +02:00
jens eb893a7f21 Fixed crash when exiting settings while service is running 2024-05-23 16:02:58 +02:00
jens 8788a89e48 Removed calendar trigger from Google version and fixed bug in startOtherActivity 2024-05-23 15:02:12 +02:00
jens bb10620883 Removed calendar trigger from Google version 2024-05-07 09:49:32 +02:00
jens 3e29054f82 New version 2024-05-05 23:39:46 +02:00
jens 9d5f0a3cef Merge remote-tracking branch 'origin/development-stable' into development-stable 2024-04-17 23:48:58 +02:00
jens 695b1f2481 New version prepared 2024-04-17 23:48:43 +02:00
jens d7357b0b0f date time repetition 2024-03-29 15:31:32 +01:00
jens e272338cc6 Date time repetition 2024-02-12 23:15:05 +01:00
jens 3dd84220a3 date time repetition 2024-02-11 17:25:42 +01:00
jens 4bc2781ee7 Date time repetition 2024-02-08 23:53:15 +01:00
jens 62bfbbb064 date time repetition 2024-02-08 20:25:54 +01:00
jens 31d167a93f New version prep, fix attempt in notification listener 2024-02-07 23:24:03 +01:00
jens 500610fb98 Merge branch 'development' into development-stable 2024-02-02 23:09:23 +01:00
jens 5ca7295c30 date time repetition 2024-01-27 17:03:27 +01:00
jens e2027a457a Merge remote-tracking branch 'origin/development' into development 2024-01-25 16:54:00 +01:00
jens 6c31b67b14 Battery charging type differentiation and other fixes 2024-01-25 16:53:43 +01:00
jens 04fe674cf6 Battery charging type differentiation 2024-01-25 14:03:39 +01:00
jens 17b3b8fafc New version prep, fix attempt in notification listener 2024-01-24 23:16:24 +01:00
jens 0d38c8bbe0 New version prep, fix attempt in notification listener 2024-01-24 14:00:34 +01:00
jens f7ff8a38e1 New version prep, fix attempt in notification listener 2024-01-21 23:46:08 +01:00
jens b7677bdcce Calendar trigger 2024-01-20 23:47:32 +01:00
jens 1ff4a15818 Calendar trigger 2024-01-18 16:28:42 +01:00
jens bd42507521 Bugfix in triggerUrl action 2024-01-15 16:42:16 +01:00
jens fe924f6fe9 Calendar trigger 2024-01-14 23:18:12 +01:00
jens dfe8594f06 Calendar trigger 2024-01-14 15:56:44 +01:00
jens 553d14b05f Calendar trigger 2024-01-10 20:01:24 +01:00
jens b38ca31df5 Calendar trigger 2024-01-09 22:56:42 +01:00
jens 6e566c664d Calendar trigger 2024-01-08 23:10:27 +01:00
jens 8c4b75232e Calendar trigger 2024-01-07 23:56:55 +01:00
jens 4521bc7d4e Calendar trigger 2024-01-07 15:15:56 +01:00
jens eaecf63724 Calendar trigger 2024-01-06 23:57:52 +01:00
jens ec62b91449 Calendar trigger 2024-01-06 17:25:27 +01:00
jens 223cca442d wifi trigger 2024-01-06 11:49:49 +01:00
jens f3613f8eb0 triggerUrl with POST params 2024-01-03 16:24:21 +01:00
jens 8b193aa89c triggerUrl with POST params 2024-01-02 16:36:10 +01:00
jens 58ec35aae5 calendar trigger 2024-01-01 13:35:21 +01:00
jens c61c5ba14c if brackets 2023-12-31 16:53:59 +01:00
jens 6e73c74b60 Added changelog for v137 2023-12-03 23:27:23 +01:00
216 changed files with 8307 additions and 3777 deletions
+15 -14
View File
@@ -3,16 +3,16 @@ plugins {
}
android {
compileSdkVersion 29
compileSdkVersion 36
defaultConfig {
applicationId "com.jens.automation2"
minSdkVersion 16
compileSdkVersion 31
buildToolsVersion '29.0.2'
minSdkVersion 19
compileSdkVersion 36
buildToolsVersion '36.0.0'
useLibrary 'org.apache.http.legacy'
versionCode 138
versionName "1.7.21"
versionCode 148
versionName "1.8.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -36,7 +36,7 @@ android {
{
dimension "version"
versionNameSuffix "-googlePlay"
targetSdkVersion 33
targetSdkVersion 36
}
/*
@@ -63,24 +63,25 @@ android {
checkReleaseBuilds false
}
namespace 'com.jens.automation2'
buildToolsVersion '36.0.0'
}
dependencies {
implementation 'org.jetbrains:annotations:15.0'
implementation 'org.jetbrains:annotations:26.1.0'
googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:18.0.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:20.0.0'
apkFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
apkFlavorImplementation 'com.google.android.gms:play-services-location:18.0.0'
apkFlavorImplementation 'com.google.android.gms:play-services-location:20.0.0'
implementation 'com.linkedin.dexmaker:dexmaker:2.25.0'
implementation 'org.apache.commons:commons-lang3:3.0'
implementation 'com.linkedin.dexmaker:dexmaker:2.28.6'
implementation 'org.apache.commons:commons-lang3:3.20.0'
//implementation "androidx.security:security-crypto:1.0.0"
//implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
testImplementation 'junit:junit:4'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
+18 -19
View File
@@ -70,15 +70,16 @@
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.hardware.sensor.proximity"/>
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-permission android:name="com.termux.permission.RUN_COMMAND" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-feature
android:name="android.hardware.telephony"
@@ -111,20 +112,11 @@
android:name="google_analytics_ssaid_collection_enabled"
android:value="false" />
<activity
android:name=".ActivityMainScreen"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivityManagePoi"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivitySettings"
android:label="@string/app_name"></activity>
<service
android:name=".AutomationService"
android:exported="false"
android:label="@string/app_name" />
android:label="@string/app_name"
android:foregroundServiceType="specialUse" />
<receiver android:name=".receivers.StartupIntentReceiver" android:enabled="true" android:exported="true">
<intent-filter>
@@ -139,6 +131,7 @@
</intent-filter>
</receiver>
<receiver android:name=".receivers.PackageReplacedReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
@@ -151,6 +144,7 @@
<receiver
android:name=".DeviceAdmin"
android:exported="true"
android:description="@string/app_name"
android:label="@string/app_name"
android:permission= "android.permission.BIND_DEVICE_ADMIN" >
@@ -162,6 +156,9 @@
</intent-filter>
</receiver>
<activity android:name=".ActivityMainScreen" android:label="@string/app_name" />
<activity android:name=".ActivityManagePoi" android:label="@string/app_name" />
<activity android:name=".ActivitySettings" android:label="@string/app_name" />
<activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityManageActionTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
@@ -190,9 +187,11 @@
<activity android:name=".ActivityManageTriggerCheckVariable" />
<activity android:name=".ActivityManageActionCopyToClipboard" />
<activity android:name=".ActivityManageActionLocationService" />
<activity android:name=".ActivityManageTriggerCharging" />
<activity
android:name=".ActivityMainTabLayout"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -217,7 +216,6 @@
</intent-filter>
-->
<!--
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
@@ -230,18 +228,20 @@
<activity android:name=".ActivityManageActionStartActivity" />
<activity android:name=".ActivityManageTriggerNfc" />
<activity android:name=".ActivityManageActionSpeakText" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageTriggerBluetooth" />
<activity android:name=".ActivityMainProfiles" />
<activity android:name=".ActivityManageProfile" />
<activity android:name=".ActivityManageTriggerWifi" />
<activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityPermissions" />
<activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity android:name=".ActivityManageTriggerProximity" />
<activity android:name=".ActivityManageActionSetSystemSetting" />
<service
android:name=".receivers.NotificationListener"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
@@ -250,7 +250,6 @@
</service>
<activity android:name=".ActivityPermissions" />
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
@@ -18,7 +18,7 @@ public class MyGoogleApiClient
public com.google.android.gms.appindexing.Action getIndexApiAction()
{
Thing object = new Thing.Builder()
.setName("ActivityMainScreen Page") // TODO: Define a title for the content shown.
.setName("ActivityMainScreen Page")
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
@@ -10,9 +10,12 @@ import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import java.util.ArrayList;
import java.util.Calendar;
@@ -373,23 +376,28 @@ public class Rule implements Comparable<Rule>
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies and has flipped since its last execution.", 4);
return true;
}
else if(hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent) && CalendarReceiver.mayRuleStillBeActivatedForPendingCalendarEvents(this))
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies, has not flipped since its last execution, but may still be executed for other calendar events.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" has not flipped since its last execution.", 4);
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " does not apply.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" does not apply.", 4);
return false;
}
public boolean applies(Context context)
{
if(AutomationService.getInstance() == null)
{
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule " + getName() + " cannot apply.", 3);
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule \"" + getName() + "\" cannot apply.", 3);
return false;
}
@@ -401,7 +409,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);
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;
}
@@ -506,8 +514,6 @@ public class Rule implements Comparable<Rule>
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggleable;
String message;
@@ -521,11 +527,35 @@ public class Rule implements Comparable<Rule>
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
/*
Make a note of Rule/CalendarEvent executed combinations
*/
if(Rule.this.hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent))
{
for(CalendarReceiver.CalendarEvent event : CalendarReceiver.getApplyingCalendarEvents(Rule.this))
{
if(!CalendarReceiver.hasEventBeenUsedInRule(Rule.this, event))
{
/*
Record only the first calendar event that matched because the rule may
be executed once for every matching event.
*/
Miscellaneous.logEvent("i", "Rule", "Executing this rule run for calender event: " + event, 5);
CalendarReceiver.addUsedPair(new CalendarReceiver.RuleEventPair(Rule.this, event));
break;
}
}
}
/*
Run actions one after another
*/
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Rule.this.getActionSet().get(i).run(automationService, doToggle);
Miscellaneous.logEvent("i", "RuleExecution", "Running action " + Rule.this.getActionSet().get(i).toStringShort() + " of rule " + Rule.this.getName(), 5);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
{
@@ -562,10 +592,7 @@ 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);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -780,4 +807,71 @@ public class Rule implements Comparable<Rule>
return null;
}
@Override
public boolean equals(@Nullable Object obj)
{
return this.getName().equals(((Rule)obj).getName());
}
public boolean hasTriggerOfType(Trigger.Trigger_Enum queryType)
{
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(queryType))
return true;
}
return false;
}
public boolean hasActionOfType(Action.Action_Enum queryType)
{
for(Action a : getActionSet())
{
if(a.getAction().equals(queryType))
return true;
}
return false;
}
public int getAmountOfTriggersForType(Trigger.Trigger_Enum type)
{
int amount = 0;
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(type))
amount++;
}
return amount;
}
public int getAmountOfActionsForType(Action.Action_Enum type)
{
int amount = 0;
for(Action a : getActionSet())
{
if(a.getAction().equals(type))
amount++;
}
return amount;
}
public static int getAmountOfActivatedRules()
{
int amount = 0;
for(Rule r : Rule.getRuleCollection())
{
if(r.isRuleActive())
amount++;
}
return amount;
}
}
+18 -18
View File
@@ -68,14 +68,16 @@
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.hardware.sensor.proximity"/>
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-permission android:name="com.termux.permission.RUN_COMMAND" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-feature
android:name="android.hardware.telephony"
@@ -108,20 +110,11 @@
android:name="google_analytics_ssaid_collection_enabled"
android:value="false" />
<activity
android:name=".ActivityMainScreen"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivityManagePoi"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivitySettings"
android:label="@string/app_name"></activity>
<service
android:name=".AutomationService"
android:exported="false"
android:label="@string/app_name" />
android:label="@string/app_name"
android:foregroundServiceType="specialUse" />
<receiver android:name=".receivers.StartupIntentReceiver" android:enabled="true" android:exported="true">
<intent-filter>
@@ -136,6 +129,7 @@
</intent-filter>
</receiver>
<receiver android:name=".receivers.PackageReplacedReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
@@ -148,6 +142,7 @@
<receiver
android:name=".DeviceAdmin"
android:exported="true"
android:description="@string/app_name"
android:label="@string/app_name"
android:permission= "android.permission.BIND_DEVICE_ADMIN" >
@@ -159,6 +154,9 @@
</intent-filter>
</receiver>
<activity android:name=".ActivityMainScreen" android:label="@string/app_name" />
<activity android:name=".ActivityManagePoi" android:label="@string/app_name" />
<activity android:name=".ActivitySettings" android:label="@string/app_name" />
<activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityManageActionTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
@@ -187,9 +185,11 @@
<activity android:name=".ActivityManageTriggerCheckVariable" />
<activity android:name=".ActivityManageActionCopyToClipboard" />
<activity android:name=".ActivityManageActionLocationService" />
<activity android:name=".ActivityManageTriggerCharging" />
<activity
android:name=".ActivityMainTabLayout"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -214,7 +214,6 @@
</intent-filter>
-->
<!--
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
@@ -227,18 +226,20 @@
<activity android:name=".ActivityManageActionStartActivity" />
<activity android:name=".ActivityManageTriggerNfc" />
<activity android:name=".ActivityManageActionSpeakText" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageTriggerBluetooth" />
<activity android:name=".ActivityMainProfiles" />
<activity android:name=".ActivityManageProfile" />
<activity android:name=".ActivityManageTriggerWifi" />
<activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityPermissions" />
<activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity android:name=".ActivityManageTriggerProximity" />
<activity android:name=".ActivityManageActionSetSystemSetting" />
<service
android:name=".receivers.NotificationListener"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
@@ -247,7 +248,6 @@
</service>
<activity android:name=".ActivityPermissions" />
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
@@ -10,7 +10,10 @@ import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@@ -344,7 +347,16 @@ public class Rule implements Comparable<Rule>
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
{
if(this.getLastExecution() != null)
{
Calendar now = Calendar.getInstance();
if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis())
return true;
}
else
return true;
}
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
@@ -361,23 +373,28 @@ public class Rule implements Comparable<Rule>
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies and has flipped since its last execution.", 4);
return true;
}
else if(hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent) && CalendarReceiver.mayRuleStillBeActivatedForPendingCalendarEvents(this))
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies, has not flipped since its last execution, but may still be executed for other calendar events.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" has not flipped since its last execution.", 4);
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " does not apply.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" does not apply.", 4);
return false;
}
public boolean applies(Context context)
{
if(AutomationService.getInstance() == null)
{
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule " + getName() + " cannot apply.", 3);
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule \"" + getName() + "\" cannot apply.", 3);
return false;
}
@@ -389,7 +406,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);
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;
}
@@ -470,8 +487,6 @@ public class Rule implements Comparable<Rule>
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggleable;
String message;
@@ -485,10 +500,34 @@ public class Rule implements Comparable<Rule>
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
/*
Make a note of Rule/CalendarEvent executed combinations
*/
if(Rule.this.hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent))
{
for(CalendarReceiver.CalendarEvent event : CalendarReceiver.getApplyingCalendarEvents(Rule.this))
{
if(!CalendarReceiver.hasEventBeenUsedInRule(Rule.this, event))
{
/*
Record only the first calendar event that matched because the rule may
be executed once for every matching event.
*/
Miscellaneous.logEvent("i", "Rule", "Executing this rule run for calender event: " + event, 5);
CalendarReceiver.addUsedPair(new CalendarReceiver.RuleEventPair(Rule.this, event));
break;
}
}
}
/*
Run actions one after another
*/
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Miscellaneous.logEvent("i", "RuleExecution", "Running action " + Rule.this.getActionSet().get(i).toStringShort() + " of rule " + Rule.this.getName(), 5);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
@@ -526,10 +565,7 @@ 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);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -744,4 +780,71 @@ public class Rule implements Comparable<Rule>
return null;
}
@Override
public boolean equals(@Nullable Object obj)
{
return this.getName().equals(((Rule)obj).getName());
}
public boolean hasTriggerOfType(Trigger.Trigger_Enum queryType)
{
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(queryType))
return true;
}
return false;
}
public boolean hasActionOfType(Action.Action_Enum queryType)
{
for(Action a : getActionSet())
{
if(a.getAction().equals(queryType))
return true;
}
return false;
}
public int getAmountOfTriggersForType(Trigger.Trigger_Enum type)
{
int amount = 0;
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(type))
amount++;
}
return amount;
}
public int getAmountOfActionsForType(Action.Action_Enum type)
{
int amount = 0;
for(Action a : getActionSet())
{
if(a.getAction().equals(type))
amount++;
}
return amount;
}
public static int getAmountOfActivatedRules()
{
int amount = 0;
for(Rule r : Rule.getRuleCollection())
{
if(r.isRuleActive())
amount++;
}
return amount;
}
}
+23 -33
View File
@@ -66,13 +66,15 @@
<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.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.hardware.sensor.proximity"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="com.termux.permission.RUN_COMMAND" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application
android:allowBackup="true"
@@ -92,22 +94,19 @@
android:name="google_analytics_ssaid_collection_enabled"
android:value="false" />
<activity
android:name=".ActivityMainScreen"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivityManagePoi"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivitySettings"
android:label="@string/app_name"></activity>
<service
android:name=".AutomationService"
android:exported="false"
android:label="@string/app_name" />
android:label="@string/app_name"
android:foregroundServiceType="specialUse" >
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Automating things on the device" />
</service>
<receiver android:name=".receivers.StartupIntentReceiver" android:enabled="true" android:exported="true">
<receiver android:name=".receivers.StartupIntentReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!--<action android:name="android.intent.action.SCREEN_ON" />-->
<!--<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />-->
@@ -145,6 +144,9 @@
</intent-filter>
</receiver>
<activity android:name=".ActivityMainScreen" android:label="@string/app_name" />
<activity android:name=".ActivityManagePoi" android:label="@string/app_name" />
<activity android:name=".ActivitySettings" android:label="@string/app_name" />
<activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityManageActionTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
@@ -172,7 +174,7 @@
<activity android:name=".ActivityManageTriggerCheckVariable" />
<activity android:name=".ActivityManageActionCopyToClipboard" />
<activity android:name=".ActivityManageActionLocationService" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity android:name=".ActivityManageTriggerCharging" />
<activity
android:name=".ActivityMainTabLayout"
@@ -201,7 +203,6 @@
</intent-filter>
-->
<!--
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
@@ -214,14 +215,16 @@
<activity android:name=".ActivityManageActionStartActivity" />
<activity android:name=".ActivityManageTriggerNfc" />
<activity android:name=".ActivityManageActionSpeakText" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageTriggerBluetooth" />
<activity android:name=".ActivityMainProfiles" />
<activity android:name=".ActivityManageProfile" />
<activity android:name=".ActivityManageTriggerWifi" />
<activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityPermissions" />
<activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity android:name=".ActivityManageTriggerProximity" />
<activity android:name=".ActivityManageActionSetSystemSetting" />
<service
android:name=".receivers.NotificationListener"
@@ -234,8 +237,6 @@
</service>
<activity android:name=".ActivityPermissions" />
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
@@ -257,17 +258,6 @@
android:exported="true"
/>
<service android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/config_accessibility_service" />
</service>
</application>
</manifest>
@@ -10,9 +10,12 @@ import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import java.util.ArrayList;
import java.util.Calendar;
@@ -347,7 +350,16 @@ public class Rule implements Comparable<Rule>
if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame))
{
if(oneTrigger.getTimeFrame().repetition > 0)
return true;
{
if(this.getLastExecution() != null)
{
Calendar now = Calendar.getInstance();
if (this.getLastExecution().getTimeInMillis() + oneTrigger.getTimeFrame().getRepetition() * 1000 <= now.getTimeInMillis())
return true;
}
else
return true;
}
}
else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.broadcastReceived))
{
@@ -364,23 +376,28 @@ public class Rule implements Comparable<Rule>
{
if(hasNotAppliedSinceLastExecution())
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " applies and has flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies and has flipped since its last execution.", 4);
return true;
}
else if(hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent) && CalendarReceiver.mayRuleStillBeActivatedForPendingCalendarEvents(this))
{
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" applies, has not flipped since its last execution, but may still be executed for other calendar events.", 4);
return true;
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " has not flipped since its last execution.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" has not flipped since its last execution.", 4);
}
else
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule " + getName() + " does not apply.", 4);
Miscellaneous.logEvent("i", "getsGreenLight()", "Rule \"" + getName() + "\" does not apply.", 4);
return false;
}
public boolean applies(Context context)
{
if(AutomationService.getInstance() == null)
{
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule " + getName() + " cannot apply.", 3);
Miscellaneous.logEvent("i", "RuleCheck", "Automation service not running. Rule \"" + getName() + "\" cannot apply.", 3);
return false;
}
@@ -392,7 +409,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);
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;
}
@@ -497,8 +514,6 @@ public class Rule implements Comparable<Rule>
protected boolean activateInternally(AutomationService automationService)
{
boolean isActuallyToggleable = isActuallyToggable();
boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this);
boolean doToggle = ruleToggle && isActuallyToggleable;
String message;
@@ -512,10 +527,34 @@ public class Rule implements Comparable<Rule>
if(Settings.startNewThreadForRuleActivation)
publishProgress(message);
/*
Make a note of Rule/CalendarEvent executed combinations
*/
if(Rule.this.hasTriggerOfType(Trigger.Trigger_Enum.calendarEvent))
{
for(CalendarReceiver.CalendarEvent event : CalendarReceiver.getApplyingCalendarEvents(Rule.this))
{
if(!CalendarReceiver.hasEventBeenUsedInRule(Rule.this, event))
{
/*
Record only the first calendar event that matched because the rule may
be executed once for every matching event.
*/
Miscellaneous.logEvent("i", "Rule", "Executing this rule run for calender event: " + event, 5);
CalendarReceiver.addUsedPair(new CalendarReceiver.RuleEventPair(Rule.this, event));
break;
}
}
}
/*
Run actions one after another
*/
for(int i = 0; i< Rule.this.getActionSet().size(); i++)
{
try
{
Miscellaneous.logEvent("i", "RuleExecution", "Running action " + Rule.this.getActionSet().get(i).toStringShort() + " of rule " + Rule.this.getName(), 5);
Rule.this.getActionSet().get(i).run(automationService, doToggle);
}
catch(Exception e)
@@ -553,10 +592,7 @@ 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);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, automationService, force);
}
public static ArrayList<Rule> findRuleCandidates(Trigger.Trigger_Enum triggerType)
@@ -771,4 +807,71 @@ public class Rule implements Comparable<Rule>
return null;
}
@Override
public boolean equals(@Nullable Object obj)
{
return this.getName().equals(((Rule)obj).getName());
}
public boolean hasTriggerOfType(Trigger.Trigger_Enum queryType)
{
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(queryType))
return true;
}
return false;
}
public boolean hasActionOfType(Action.Action_Enum queryType)
{
for(Action a : getActionSet())
{
if(a.getAction().equals(queryType))
return true;
}
return false;
}
public int getAmountOfTriggersForType(Trigger.Trigger_Enum type)
{
int amount = 0;
for(Trigger t : getTriggerSet())
{
if(t.getTriggerType().equals(type))
amount++;
}
return amount;
}
public int getAmountOfActionsForType(Action.Action_Enum type)
{
int amount = 0;
for(Action a : getActionSet())
{
if(a.getAction().equals(type))
amount++;
}
return amount;
}
public static int getAmountOfActivatedRules()
{
int amount = 0;
for(Rule r : Rule.getRuleCollection())
{
if(r.isRuleActive())
amount++;
}
return amount;
}
}
@@ -8,8 +8,11 @@ import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class Action
@@ -18,7 +21,10 @@ public class Action
public static final String actionParameter2Split = "ap2split";
public static final String intentPairSeparator = "intPairSplit";
public static final String actionParameters2SeparatorInner = "a2splitInner";
public static final String actionParameters2SeparatorOuter = "a2splitOuter";
public static final String vibrateSeparator = ",";
public static final String httpErrorDefaultText = "HTTP_ERROR";
public enum Action_Enum
{
@@ -28,13 +34,9 @@ public class Action
setWifiTethering,
setBluetoothTethering,
setDisplayRotation,
turnWifiOn,turnWifiOff,
turnBluetoothOn,turnBluetoothOff,
triggerUrl,
changeSoundProfile,
turnUsbTetheringOn,turnUsbTetheringOff,
turnWifiTetheringOn,turnWifiTetheringOff,
enableScreenRotation,disableScreenRotation,
startOtherActivity,
waitBeforeNextAction,
turnScreenOnOrOff,
@@ -55,9 +57,10 @@ public class Action
startPhoneCall,
stopPhoneCall,
copyToClipboard,
takeScreenshot,
setLocationService,
sendTextMessage;
sendTextMessage,
takeScreenshot,
setSystemSetting;
public String getFullName(Context context)
{
@@ -75,14 +78,6 @@ public class Action
return context.getResources().getString(R.string.actionSetUsbTethering);
case setDisplayRotation:
return context.getResources().getString(R.string.actionSetDisplayRotation);
case turnWifiOn:
return context.getResources().getString(R.string.actionTurnWifiOn);
case turnWifiOff:
return context.getResources().getString(R.string.actionTurnWifiOff);
case turnBluetoothOn:
return context.getResources().getString(R.string.actionTurnBluetoothOn);
case turnBluetoothOff:
return context.getResources().getString(R.string.actionTurnBluetoothOff);
case triggerUrl:
return context.getResources().getString(R.string.actionTriggerUrl);
case changeSoundProfile:
@@ -91,14 +86,6 @@ public class Action
return context.getResources().getString(R.string.actionTurnUsbTetheringOn);
case turnUsbTetheringOff:
return context.getResources().getString(R.string.actionTurnUsbTetheringOff);
case turnWifiTetheringOn:
return context.getResources().getString(R.string.actionTurnWifiTetheringOn);
case turnWifiTetheringOff:
return context.getResources().getString(R.string.actionTurnWifiTetheringOff);
case enableScreenRotation:
return context.getResources().getString(R.string.actionEnableScreenRotation);
case disableScreenRotation:
return context.getResources().getString(R.string.actionDisableScreenRotation);
case startOtherActivity:
return context.getResources().getString(R.string.startOtherActivity);
case waitBeforeNextAction:
@@ -145,6 +132,8 @@ public class Action
return context.getResources().getString(R.string.takeScreenshot);
case setLocationService:
return context.getResources().getString(R.string.setLocationServiceCapital);
case setSystemSetting:
return context.getResources().getString(R.string.setSystemSettingCapital);
default:
return "Unknown";
}
@@ -340,16 +329,33 @@ public class Action
if (this.getAction().equals(Action_Enum.triggerUrl))
{
String[] components = parameter2.split(";");
String[] components;
if(parameter2.contains(Action.actionParameter2Split))
components = parameter2.split(Action.actionParameter2Split);
else
components = parameter2.split(";");
if (components.length >= 3)
{
returnString.append(" (");
if(components.length >= 4)
returnString.append(components[3]);
else
returnString.append(ActivityManageActionTriggerUrl.methodGet);
returnString.append(")");
returnString.append(": " + components[2]);
if (parameter1)
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingAuthentication) + ".");
}
else
{
returnString.append(" (");
returnString.append(ActivityManageActionTriggerUrl.methodGet);;
returnString.append(")");
returnString.append(": " + components[0]);
}
}
else if (this.getAction().equals(Action_Enum.startOtherActivity))
{
@@ -471,25 +477,9 @@ public class Action
for(Action_Enum action : Action_Enum.values())
{
if( // exclusion for deprecated types
!action.toString().equals("turnWifiOn")
&&
!action.toString().equals("turnWifiOff")
&&
!action.toString().equals("turnBluetoothOn")
&&
!action.toString().equals("turnBluetoothOff")
&&
!action.toString().equals("turnUsbTetheringOn")
&&
!action.toString().equals("turnUsbTetheringOff")
&&
!action.toString().equals("turnWifiTetheringOn")
&&
!action.toString().equals("turnWifiTetheringOff")
&&
!action.toString().equals("enableScreenRotation")
&&
!action.toString().equals("disableScreenRotation")
) // exclusion for deprecated types
actionTypesList.add(action.toString());
}
@@ -503,27 +493,11 @@ public class Action
for(Action_Enum action : Action_Enum.values())
{
if( // exclusion for deprecated types
!action.toString().equals("turnWifiOn")
&&
!action.toString().equals("turnWifiOff")
&&
!action.toString().equals("turnBluetoothOn")
&&
!action.toString().equals("turnBluetoothOff")
&&
!action.toString().equals("turnUsbTetheringOn")
&&
!action.toString().equals("turnUsbTetheringOff")
&&
!action.toString().equals("turnWifiTetheringOn")
&&
!action.toString().equals("turnWifiTetheringOff")
&&
!action.toString().equals("enableScreenRotation")
&&
!action.toString().equals("disableScreenRotation")
) // exclusion for deprecated types
actionTypesList.add(action.getFullName(context));
actionTypesList.add(action.getFullName(context));
}
return (String[])actionTypesList.toArray(new String[actionTypesList.size()]);
@@ -550,7 +524,7 @@ public class Action
triggerUrl(context);
break;
case setBluetooth:
Actions.setBluetooth(context, getParameter1(), toggleActionIfPossible);
boolean result = Actions.setBluetooth(context, getParameter1(), toggleActionIfPossible);
break;
case setUsbTethering:
Actions.setUsbTethering(context, getParameter1(), toggleActionIfPossible);
@@ -665,6 +639,10 @@ public class Action
case setLocationService:
Actions.setLocationService(Integer.parseInt(this.getParameter2()), AutomationService.getInstance());
break;
case setSystemSetting:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
Actions.setSystemSetting(this.getParameter2(), AutomationService.getInstance());
break;
default:
Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3);
break;
@@ -678,13 +656,19 @@ public class Action
}
private void triggerUrl(Context context)
{
{
//TODO: Check if data needs to be escaped
String username = null;
String password = null;
String method = ActivityManageActionTriggerUrl.methodGet;
String url;
String params = null;
String[] components = getParameter2().split(";");
String[] components;
if(getParameter2().contains(Action.actionParameter2Split))
components = getParameter2().split(Action.actionParameter2Split, -1);
else
components = getParameter2().split(";", -1);
if(components.length >= 3)
{
@@ -694,6 +678,11 @@ public class Action
if(components.length >= 4)
method = components[3];
if(components.length >= 5)
{
params = components[4];
}
}
else // compatibility for very old versions which haven't upgraded, yet.
url = components[0];
@@ -701,15 +690,21 @@ public class Action
try
{
url = Miscellaneous.replaceVariablesInText(url, context);
// if(!StringUtils.isEmpty(params))
// params = URLEncoder.encode(Miscellaneous.replaceVariablesInText(params, context), "UTF-8");
Actions myAction = new Actions();
Miscellaneous.logEvent("i", "HTTP", "Attempting download of " + url, 4); //getResources().getString("attemptingDownloadOf");
/*
Theoretically credentials could be saved, but authentication has been turned off afterwards.
The following if clause is there to force username and password to be null.
*/
if(this.getParameter1()) // use authentication
new DownloadTask().execute(url, username, password, method);
new DownloadTask().execute(url, username, password, method, params);
else
new DownloadTask().execute(url, null, null);
new DownloadTask().execute(url, null, null, method, params);
}
catch(Exception e)
{
@@ -724,35 +719,60 @@ public class Action
{
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.uncaughtExceptionHandler);
int attempts=1;
int attempts = 1;
String urlString=parameters[0];
String urlUsername = null;
String urlPassword = null;
String method = ActivityManageActionTriggerUrl.methodGet;
Map<String,String> httpParams = new HashMap<>();
if(parameters.length >= 3)
{
urlUsername = parameters[1];
urlPassword = parameters[2];
urlPassword = parameters[2];
if(parameters.length >= 4)
method = parameters[3];
if(parameters.length >= 5 && parameters[4] != null)
{
// has params
String[] paramPairs = parameters[4].split(Action.actionParameters2SeparatorOuter);
String value = "";
for(String pair : paramPairs)
{
String[] pieces = pair.split(Action.actionParameters2SeparatorInner);
try
{
value = Miscellaneous.replaceVariablesInText(pieces[1], Miscellaneous.getAnyContext());
}
catch (Exception e)
{
value = "error";
}
if(pieces.length == 2)
httpParams.put(pieces[0], value);
}
}
}
String response = "HTTP_ERROR";
String response = httpErrorDefaultText;
if(Settings.httpAttempts < 1)
Miscellaneous.logEvent("w", "HTTP Request", Miscellaneous.getAnyContext().getResources().getString(R.string.cantDownloadTooFewRequestsInSettings), 3);
while(attempts <= Settings.httpAttempts && response.equals("httpError"))
while(attempts <= Settings.httpAttempts && response.equals(httpErrorDefaultText))
{
Miscellaneous.logEvent("i", "HTTP Request", "Attempt " + String.valueOf(attempts++) + " of " + String.valueOf(Settings.httpAttempts), 3);
// Either thorough checking or no encryption
if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https"))
response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method);
else
response = Miscellaneous.downloadURLwithoutCertificateChecking(urlString, urlUsername, urlPassword, method);
// if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https"))
response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method, httpParams);
// else
// response = Miscellaneous.downloadUrlWithoutCertificateChecking(urlString, urlUsername, urlPassword, method, httpParams);
try
{
File diff suppressed because it is too large Load Diff
@@ -8,6 +8,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
@@ -40,6 +41,7 @@ public class ActivityControlCenter extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_control_center);
@@ -98,8 +100,17 @@ public class ActivityControlCenter extends Activity
@Override
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, requestCodeImport);
AlertDialog dialog = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.importChooseFolderNotice), ActivityControlCenter.this);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, requestCodeImport);
}
});
dialog.show();
}
});
@@ -22,6 +22,7 @@ public class ActivityDisplayLongMessage extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_display_long_message);
tvMessageTitle = (TextView)findViewById(R.id.tvMessageTitle);
@@ -14,6 +14,7 @@ public class ActivityHelp extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(layout.activity_help_text);
TextView tvHelpTextEnergySaving = (TextView) findViewById(R.id.tvHelpTextEnergySaving);
@@ -45,6 +45,7 @@ public class ActivityMainPoi extends ActivityGeneric
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.main_poi_layout);
instance = this;
@@ -41,6 +41,7 @@ public class ActivityMainProfiles extends ActivityGeneric
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.main_profile_layout);
instance = this;
@@ -49,6 +49,7 @@ public class ActivityMainRules extends ActivityGeneric
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.main_rule_layout);
instance = this;
@@ -196,7 +197,14 @@ public class ActivityMainRules extends ActivityGeneric
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getResources().getString(R.string.whatToDoWithRule));
alertDialogBuilder.setItems(new String[]{ getResources().getString(R.string.runManually), getResources().getString(R.string.edit), getResources().getString(R.string.deleteCapital), getResources().getString(R.string.clone) }, new DialogInterface.OnClickListener()
String toggleEnabled;
if(ruleThisIsAbout.isRuleActive())
toggleEnabled = getResources().getString(R.string.disable);
else
toggleEnabled = getResources().getString(R.string.enable);
alertDialogBuilder.setItems(new String[]{ getResources().getString(R.string.runManually), getResources().getString(R.string.edit), getResources().getString(R.string.deleteCapital), toggleEnabled, getResources().getString(R.string.clone) }, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
@@ -248,6 +256,19 @@ public class ActivityMainRules extends ActivityGeneric
deleteDialog.show();
break;
case 3:
ruleToEdit = ruleThisIsAbout;
if(ruleToEdit.isRuleActive())
ruleToEdit.setRuleActive(false);
else
ruleToEdit.setRuleActive(true);
if(ruleToEdit.change(ActivityMainRules.this))
{
ruleToEdit = null; //clear cache
updateListView();
}
break;
case 4:
ruleToEdit = ruleThisIsAbout;
if(ruleToEdit.cloneRule(ActivityMainRules.this))
{
@@ -11,6 +11,7 @@ import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
@@ -46,7 +47,7 @@ public class ActivityMainScreen extends ActivityGeneric
ToggleButton toggleService, tbLockSound;
Button bShowHelp, bPrivacy, bAddSoundLockTIme, bDonate, bControlCenter;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration;
TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration, tvContactNotice;
ListView lvRuleHistory;
ArrayAdapter<Rule> ruleHistoryListViewAdapter;
@@ -56,6 +57,7 @@ public class ActivityMainScreen extends ActivityGeneric
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.main_overview_layout);
activityMainScreenInstance = this;
@@ -83,10 +85,14 @@ public class ActivityMainScreen extends ActivityGeneric
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
bDonate = (Button)findViewById(R.id.bDonate);
tvContactNotice = (TextView) findViewById(R.id.tvContactNotice);
if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))
bDonate.setVisibility(View.VISIBLE);
// Make links clickable
tvContactNotice.setMovementMethod(LinkMovementMethod.getInstance());
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
toggleService.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@@ -122,9 +128,9 @@ public class ActivityMainScreen extends ActivityGeneric
@Override
public void onClick(View v)
{
String privacyPolicyUrl = "https://server47.de/donate";
String donationUrl = "https://server47.de/donate";
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyUrl));
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(donationUrl));
startActivity(browserIntent);
}
});
@@ -526,15 +532,30 @@ public class ActivityMainScreen extends ActivityGeneric
{
if (Rule.getRuleCollection().size() > 0)
{
if(Rule.getAmountOfActivatedRules() == 0)
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStartNoActivatedRules), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
return;
}
if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34 && !ActivityPermissions.havePermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, context))
{
Toast.makeText(context, context.getResources().getString(R.string.permissionForegroundServiceTypeSpecialUseRequired), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
return;
}
if (!AutomationService.isMyServiceRunning(context))
{
// if(myServiceIntent == null) //do we need that line?????
myServiceIntent = new Intent(context, AutomationService.class);
myServiceIntent.putExtra("startAtBoot", startAtBoot);
context.startService(myServiceIntent);
} else
}
else
Miscellaneous.logEvent("w", "Service", context.getResources().getString(R.string.logServiceAlreadyRunning), 3);
} else
}
else
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
@@ -582,7 +603,7 @@ public class ActivityMainScreen extends ActivityGeneric
Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android9RecordAudioNotice) + " " + getResources().getString(R.string.messageNotShownAgain), ActivityMainScreen.this).show();
}
if(Build.VERSION.SDK_INT >= 29 && !Settings.noticeAndroid10WifiShown && Rule.isAnyRuleUsing(Action.Action_Enum.setWifi))
if(Miscellaneous.getTargetSDK(ActivityMainScreen.this) >= 29 && !Settings.noticeAndroid10WifiShown && Rule.isAnyRuleUsing(Action.Action_Enum.setWifi))
{
Settings.noticeAndroid10WifiShown = true;
Settings.writeSettings(ActivityMainScreen.this);
@@ -5,6 +5,7 @@ import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.TabHost;
@@ -24,6 +25,7 @@ public class ActivityMainTabLayout extends TabActivity
super.onCreate(savedInstanceState);
Settings.readFromPersistentStorage(ActivityMainTabLayout.this);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
if(Settings.tabsPlacement == 1)
setContentView(R.layout.main_tab_layout_tabs_at_bottom);
@@ -60,22 +62,24 @@ public class ActivityMainTabLayout extends TabActivity
tabHost.setCurrentTab(Settings.startScreen);
}
@Override
protected void onResume()
{
super.onResume();
Miscellaneous.setDisplayLanguage(this);
// Miscellaneous.logEvent("i", "NFC", "ActivityMainTabLayout.onResume().", 5);
NfcReceiver.checkIntentForNFC(this, getIntent());
// NfcReceiver.checkIntentForNFC(this, new Intent(this.getApplicationContext(), this.getClass()));
if(!(getIntent().getAction() == null || getIntent().getAction().isEmpty()) && getIntent().getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
{
NfcReceiver.checkIntentForNFC(this, getIntent());
moveTaskToBack(true);
}
}
@Override
protected void onNewIntent(Intent intent)
{
// Miscellaneous.logEvent("i", "NFC", "ActivityMainTabLayout.onNewIntent().", 5);
// setIntent(intent);
NfcReceiver.checkIntentForNFC(this, intent);
}
}
@@ -27,6 +27,7 @@ public class ActivityManageActionBrightnessSetting extends Activity
{
setContentView(R.layout.activity_manage_action_brightness_settings);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
super.onCreate(savedInstanceState);
chkAutoBrightness = (CheckBox)findViewById(R.id.chkAutoBrightness);
@@ -260,6 +260,7 @@ public class ActivityManageActionCloseNotification extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_close_notification);
etNotificationTitle = (EditText)findViewById(R.id.etNotificationTitle);
@@ -20,6 +20,7 @@ public class ActivityManageActionControlMedia extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_control_media);
rbMediaPlayPause = (RadioButton)findViewById(R.id.rbMediaPlayPause);
@@ -20,6 +20,7 @@ public class ActivityManageActionCopyToClipboard extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_copy_to_clipboard);
bSaveCopyToClipboard = (Button) findViewById(R.id.bSaveCopyToClipboard);
@@ -25,6 +25,7 @@ public class ActivityManageActionCreateNotification extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_create_notification);
etNotificationTitle = (EditText) findViewById(R.id.etNotificationTitle);
@@ -20,6 +20,7 @@ public class ActivityManageActionLocationService extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_location_service);
rbActionLocationServiceOff = (RadioButton) findViewById(R.id.rbActionLocationServiceOff);
@@ -22,6 +22,7 @@ public class ActivityManageActionMakePhoneCall extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_make_phone_call);
etTargetPhoneNumber = (EditText)findViewById(R.id.etTargetPhoneNumber);
@@ -27,6 +27,7 @@ public class ActivityManageActionPlaySound extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_play_sound);
chkPlaySoundAlwaysPlay = (CheckBox)findViewById(R.id.chkPlaySoundAlwaysPlay);
@@ -29,6 +29,7 @@ public class ActivityManageActionRunExecutable extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_run_executable);
chkRunExecAsRoot = (CheckBox)findViewById(R.id.chkRunExecAsRoot);
@@ -38,6 +38,7 @@ public class ActivityManageActionSendBroadcast extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_send_broadcast);
etBroadcastToSend = (EditText)findViewById(R.id.etBroadcastToSend);
@@ -236,8 +237,6 @@ public class ActivityManageActionSendBroadcast extends Activity
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
}
@@ -49,6 +49,7 @@ public class ActivityManageActionSendTextMessage extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_send_textmessage);
etSendTextMessage = (EditText)findViewById(R.id.etSendTextMessage);
@@ -0,0 +1,182 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class ActivityManageActionSetSystemSetting extends Activity
{
Spinner spinnerSettingTarget, spinnerSettingDataType;
EditText etSettingName, etSettingValue;
Button bSaveSetSystemSetting;
TextView tvSetSystemSettingExamples, tvSetSystemSettingNoticeWriteSecureSettings;
ArrayAdapter<String> settingTargetSpinnerAdapter, settingDataTypeSpinnerAdapter;
protected final static String[] targets = { "Global", "System", "Secure" };
protected final static String[] dataTypes = { "String", "Long", "Int", "Float" };
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_set_system_setting);
spinnerSettingTarget = (Spinner) findViewById(R.id.spinnerSettingTarget);
spinnerSettingDataType = (Spinner) findViewById(R.id.spinnerSettingDataType);
etSettingName = (EditText)findViewById(R.id.etSettingName);
etSettingValue = (EditText)findViewById(R.id.etSettingValue);
bSaveSetSystemSetting = (Button)findViewById(R.id.bSaveSetSystemSetting);
tvSetSystemSettingExamples = (TextView)findViewById(R.id.tvSetSystemSettingExamples);
tvSetSystemSettingNoticeWriteSecureSettings = (TextView)findViewById(R.id.tvSetSystemSettingNoticeWriteSecureSettings);
settingTargetSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, targets);
spinnerSettingTarget.setAdapter(settingTargetSpinnerAdapter);
settingTargetSpinnerAdapter.notifyDataSetChanged();
settingDataTypeSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, dataTypes);
spinnerSettingDataType.setAdapter(settingDataTypeSpinnerAdapter);
settingDataTypeSpinnerAdapter.notifyDataSetChanged();
tvSetSystemSettingExamples.setMovementMethod(LinkMovementMethod.getInstance());
if(ActivityPermissions.havePermission(Manifest.permission.WRITE_SECURE_SETTINGS, ActivityManageActionSetSystemSetting.this))
tvSetSystemSettingNoticeWriteSecureSettings.setVisibility(View.GONE);
else
tvSetSystemSettingNoticeWriteSecureSettings.setVisibility(View.VISIBLE);
// Make links clickable
tvSetSystemSettingNoticeWriteSecureSettings.setMovementMethod(LinkMovementMethod.getInstance());
spinnerSettingDataType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l)
{
if(dataTypes[i].equalsIgnoreCase("String"))
etSettingValue.setInputType(InputType.TYPE_CLASS_TEXT);
else if(dataTypes[i].equalsIgnoreCase("Float"))
etSettingValue.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
else
etSettingValue.setInputType(InputType.TYPE_CLASS_NUMBER);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView)
{
}
});
bSaveSetSystemSetting.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if(etSettingName.getText().toString().isEmpty())
{
Toast.makeText(getBaseContext(), getResources().getString(R.string.enterAname), Toast.LENGTH_LONG).show();
return;
}
if(etSettingValue.getText().toString().isEmpty())
{
Toast.makeText(getBaseContext(), getResources().getString(R.string.enterAvalue), Toast.LENGTH_LONG).show();
return;
}
else
{
String selectedDataType = dataTypes[spinnerSettingDataType.getSelectedItemPosition()];
if(
selectedDataType.equalsIgnoreCase("Int")
||
selectedDataType.equalsIgnoreCase("Long")
)
{
if(Miscellaneous.isNumericDecimal(etSettingValue.getText().toString()) || !Miscellaneous.isNumeric(etSettingValue.getText().toString()))
{
Toast.makeText(ActivityManageActionSetSystemSetting.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
}
else if(selectedDataType.equalsIgnoreCase("Float"))
{
if(!Miscellaneous.isNumeric(etSettingValue.getText().toString()))
{
Toast.makeText(ActivityManageActionSetSystemSetting.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
}
}
Intent returnIntent = new Intent();
String param2Data = targets[spinnerSettingTarget.getSelectedItemPosition()] + Action.actionParameter2Split + dataTypes[spinnerSettingDataType.getSelectedItemPosition()] + Action.actionParameter2Split + etSettingName.getText().toString() + Action.actionParameter2Split + etSettingValue.getText().toString();
returnIntent.putExtra(ActivityManageRule.intentNameActionParameter1, false);
returnIntent.putExtra(ActivityManageRule.intentNameActionParameter2, param2Data);
setResult(RESULT_OK, returnIntent);
finish();
}
});
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
{
// dataType, setting name, setting value
String[] components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(Action.actionParameter2Split, -1);
if(components.length == 4)
{
int positionTarget = Miscellaneous.arraySearchIndexOf(targets, components[0], false, true);
int positionDataType = Miscellaneous.arraySearchIndexOf(dataTypes, components[1], false, true);
if(positionDataType >= 0)
{
spinnerSettingTarget.setSelection(positionTarget);
spinnerSettingDataType.setSelection(positionDataType);
etSettingName.setText(components[2]);
etSettingValue.setText(components[3]);
}
}
else
{
int position = Miscellaneous.arraySearchIndexOf(dataTypes, components[0], false, true);
if (position >= 0)
{
spinnerSettingDataType.setSelection(position);
etSettingName.setText(components[1]);
etSettingValue.setText(components[2]);
}
}
}
}
private void updateListView()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update spinnerSettingDataType", 4);
try
{
if(spinnerSettingDataType.getAdapter() == null)
spinnerSettingDataType.setAdapter(settingDataTypeSpinnerAdapter);
settingDataTypeSpinnerAdapter.notifyDataSetChanged();
}
catch(NullPointerException e)
{}
}
}
@@ -1,6 +1,6 @@
package com.jens.automation2;
import static com.jens.automation2.ActivityManageActionTriggerUrl.edit;
//import static com.jens.automation2.ActivityManageActionTriggerUrl.edit;
import android.app.Activity;
import android.content.Intent;
@@ -25,6 +25,7 @@ public class ActivityManageActionSetVariable extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_set_variable);
etVariableSetKey = (EditText)findViewById(R.id.etVariableSetKey);
@@ -23,6 +23,7 @@ public class ActivityManageActionSpeakText extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_speak_text);
etSpeakText = (EditText)findViewById(R.id.etTextToSpeak);
@@ -32,7 +33,7 @@ public class ActivityManageActionSpeakText extends Activity
@Override
public void onClick(View v)
{
if(etSpeakText.getText().toString().length()>0)
if(!etSpeakText.getText().toString().isEmpty())
{
if(resultingAction == null)
{
@@ -53,11 +53,11 @@ public class ActivityManageActionStartActivity extends Activity
Button bSelectApp, bAddIntentPair, bSaveActionStartOtherActivity, showStartProgramExamples;
Spinner spinnerParameterType;
RadioGroup rgAppStartupType;
boolean edit = false;
// boolean edit = false;
ProgressDialog progressDialog = null;
RadioButton rbStartAppSelectByActivity, rbStartAppSelectByAction, rbStartAppByActivity, rbStartAppByBroadcast, rbStartAppByService, rbStartAppByForegroundService;
final String urlShowExamples = "https://server47.de/automation/examples_startProgram.html";
final String urlShowExamples = "https://server47.de/automation/examples.html";
public final static String startByActivityString = "0";
public final static String startByBroadcastString = "1";
public final static String startByServiceString = "2";
@@ -70,6 +70,7 @@ public class ActivityManageActionStartActivity extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_start_activity);
lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs);
@@ -95,8 +96,6 @@ public class ActivityManageActionStartActivity extends Activity
spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
intentTypeSpinnerAdapter.notifyDataSetChanged();
etClassName.setEnabled(false);
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
bSelectApp.setOnClickListener(new OnClickListener()
{
@@ -233,27 +232,29 @@ public class ActivityManageActionStartActivity extends Activity
String parameter2 = "";
if (rbStartAppSelectByActivity.isChecked())
parameter2 += etPackageName.getText().toString() + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
else
{
if (etPackageName.getText().toString() != null && etPackageName.getText().toString().length() > 0)
parameter2 += etPackageName.getText().toString() + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
else
parameter2 += Actions.dummyPackageString + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
/*
0 = packageName
1 = className
2 = activityName/actionName
3 = startType
4 = parameters
*/
// if(etClassName.getText().toString().length() > 0)
parameter2 += Action.actionParameter2Split + etClassName.getText().toString();
}
parameter2 += etPackageName.getText().toString()
+ Action.actionParameter2Split
+ etClassName.getText().toString()
+ Action.actionParameter2Split
+ etActivityOrActionPath.getText().toString()
+ Action.actionParameter2Split;
if (rbStartAppByActivity.isChecked())
parameter2 += Action.actionParameter2Split + startByActivityString;
parameter2 += startByActivityString;
else if(rbStartAppByService.isChecked())
parameter2 += Action.actionParameter2Split + startByServiceString;
parameter2 += startByServiceString;
else if(rbStartAppByForegroundService.isChecked())
parameter2 += Action.actionParameter2Split + startByForegroundServiceString;
parameter2 += startByForegroundServiceString;
else
parameter2 += Action.actionParameter2Split + startByBroadcastString;
parameter2 += startByBroadcastString;
for (String s : intentPairList)
parameter2 += Action.actionParameter2Split + s;
@@ -292,8 +293,6 @@ public class ActivityManageActionStartActivity extends Activity
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
@@ -319,23 +318,6 @@ public class ActivityManageActionStartActivity extends Activity
}
});
rgAppStartupType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i)
{
if(rbStartAppByActivity.isChecked())
etClassName.setEnabled(false);
else if (rbStartAppByBroadcast.isChecked())
etClassName.setEnabled(false);
else if(rbStartAppByService.isChecked())
etClassName.setEnabled(true);
else if(rbStartAppByForegroundService.isChecked())
etClassName.setEnabled(true);
}
});
Intent i = getIntent();
if(i.hasExtra(ActivityManageRule.intentNameActionParameter1))
loadValuesIntoGui(i);
@@ -628,52 +610,36 @@ public class ActivityManageActionStartActivity extends Activity
rbStartAppSelectByActivity.setChecked(!selectionByAction);
rbStartAppSelectByAction.setChecked(selectionByAction);
String[] params;
String partsString = input.getStringExtra(ActivityManageRule.intentNameActionParameter2);
/*
0 = packageName
1 = className
2 = activityName/actionName
3 = startType
4 = parameters
*/
if(partsString.contains(Action.actionParameter2Split))
params = partsString.split(Action.actionParameter2Split);
else
params = partsString.split(";");
try
{
String[] params;
String partsString = input.getStringExtra(ActivityManageRule.intentNameActionParameter2);
if(partsString.contains(Action.actionParameter2Split))
params = partsString.split(Action.actionParameter2Split, -1);
else
params = partsString.split(";", -1);
etPackageName.setText(params[0]);
etClassName.setText(params[1]);
etActivityOrActionPath.setText(params[2]);
if(Miscellaneous.isNumeric(params[2])) // old configuration file
{
rbStartAppByActivity.setChecked(params[2].equals(startByActivityString));
rbStartAppByBroadcast.setChecked(params[2].equals(startByBroadcastString));
rbStartAppByService.setChecked(params[2].equals(startByServiceString));
}
else
{
rbStartAppByActivity.setChecked(params[3].equals(startByActivityString));
rbStartAppByBroadcast.setChecked(params[3].equals(startByBroadcastString));
rbStartAppByService.setChecked(params[3].equals(startByServiceString));
rbStartAppByForegroundService.setChecked(params[3].equals(startByForegroundServiceString));
}
int startIndex = -1;
if(!selectionByAction)
{
etPackageName.setText(params[0]);
etActivityOrActionPath.setText(params[1]);
}
else
{
if(!params[0].contains(Actions.dummyPackageString))
etPackageName.setText(params[0]);
etActivityOrActionPath.setText(params[1]);
etClassName.setText(params[2]);
}
if (params.length >= 4)
startIndex = 4;
if(startIndex > -1 && params.length > startIndex)
{
intentPairList.clear();
for(int i=startIndex; i<params.length; i++)
for(int i=4; i<params.length; i++)
{
if(lvIntentPairs.getVisibility() != View.VISIBLE)
lvIntentPairs.setVisibility(View.VISIBLE);
@@ -683,6 +649,10 @@ public class ActivityManageActionStartActivity extends Activity
updateIntentPairList();
}
catch(Exception e)
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.errorLoadingValues), Toast.LENGTH_LONG).show();
}
}
private void updateIntentPairList()
@@ -1,6 +1,10 @@
package com.jens.automation2;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
@@ -15,36 +19,41 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Map;
public class ActivityManageActionTriggerUrl extends Activity
{
Button bSaveTriggerUrl;
EditText etTriggerUrl, etTriggerUrlUsername, etTriggerUrlPassword;
Button bSaveTriggerUrl, bAddHttpParam;
EditText etTriggerUrl, etTriggerUrlUsername, etTriggerUrlPassword, etParameterName, etParameterValue;
ListView lvTriggerUrlPostParameters;
CheckBox chkTriggerUrlUseAuthentication;
RadioButton rbTriggerUrlMethodGet, rbTriggerUrlMethodPost;
TableLayout tlTriggerUrlAuthentication;
TextView tvHttpParameterExplanation;
ArrayAdapter<String> httpParametersAdapter;
private ArrayList<String> httpParamsList = new ArrayList<>();
ArrayAdapter<Map<String,String>> lvTriggerUrlPostParametersAdapter;
// private String existingUrl = "";
public static final String methodGet = "GET";
public static final String methodPost = "POST";
public static boolean edit = false;
public static Action resultingAction = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_action_trigger_url);
etTriggerUrl = (EditText)findViewById(R.id.etTriggerUrl);
@@ -56,6 +65,32 @@ public class ActivityManageActionTriggerUrl extends Activity
bSaveTriggerUrl = (Button)findViewById(R.id.bSaveSpeakText);
rbTriggerUrlMethodGet = (RadioButton) findViewById(R.id.rbTriggerUrlMethodGet);
rbTriggerUrlMethodPost = (RadioButton) findViewById(R.id.rbTriggerUrlMethodPost);
etTriggerUrl = (EditText) findViewById(R.id.etTriggerUrl);
etParameterName = (EditText) findViewById(R.id.etParameterName);
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
bAddHttpParam = (Button)findViewById(R.id.bAddHttpParam);
tvHttpParameterExplanation = (TextView)findViewById(R.id.tvHttpParameterExplanation);
etParameterName.setEnabled(false);
etParameterValue.setEnabled(false);
bAddHttpParam.setEnabled(false);
rbTriggerUrlMethodPost.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
etParameterName.setEnabled(checked);
etParameterValue.setEnabled(checked);
bAddHttpParam.setEnabled(checked);
if(checked)
lvTriggerUrlPostParameters.setVisibility(View.VISIBLE);
}
});
tvHttpParameterExplanation.setText(String.format(getResources().getString(R.string.httpParametersExplanation), Miscellaneous.httpMainData, Miscellaneous.doNoEncodingString));
httpParametersAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, httpParamsList);
bSaveTriggerUrl.setOnClickListener(new OnClickListener()
{
@@ -64,35 +99,39 @@ public class ActivityManageActionTriggerUrl extends Activity
{
if(etTriggerUrl.getText().toString().length() > 0)
{
if(resultingAction == null)
{
resultingAction = new Action();
}
Intent returnIntent = new Intent();
resultingAction.setAction(Action_Enum.triggerUrl);
resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
String username = etTriggerUrlUsername.getText().toString();
String password = etTriggerUrlPassword.getText().toString();
if(username == null)
username = "";
if(password == null)
password = "";
returnIntent.putExtra(ActivityManageRule.intentNameActionParameter1, chkTriggerUrlUseAuthentication.isChecked());
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
String username = etTriggerUrlUsername.getText().toString();
String password = etTriggerUrlPassword.getText().toString();
ActivityManageActionTriggerUrl.resultingAction.setParameter2(
username + ";" +
password + ";" +
etTriggerUrl.getText().toString().trim() + ";" +
method
);
if(username == null)
username = "";
backToRuleManager();
if(password == null)
password = "";
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
String httpParams = "";
for (String s : httpParamsList)
httpParams += Action.actionParameters2SeparatorOuter + s;
if(httpParams.length() > 0)
httpParams = httpParams.substring(Action.actionParameters2SeparatorOuter.length());
returnIntent.putExtra(ActivityManageRule.intentNameActionParameter2,
username + Action.actionParameter2Split +
password + Action.actionParameter2Split +
etTriggerUrl.getText().toString().trim() + Action.actionParameter2Split +
method + Action.actionParameter2Split +
httpParams
);
setResult(RESULT_OK, returnIntent);
finish();
}
else
Toast.makeText(getBaseContext(), getResources().getString(R.string.urlTooShort), Toast.LENGTH_LONG).show();
@@ -133,17 +172,21 @@ public class ActivityManageActionTriggerUrl extends Activity
}
});
updateListView();
ActivityManageActionTriggerUrl.edit = getIntent().getBooleanExtra("edit", false);
if(edit)
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
{
// username,password,URL
String[] components = ActivityManageActionTriggerUrl.resultingAction.getParameter2().split(";");
// username,password,URL,etc.
String[] components;
if(getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).contains(Action.actionParameter2Split))
components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(Action.actionParameter2Split, -1);
else
components = getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2).split(";", -1);
if(components.length >= 3)
{
etTriggerUrl.setText(components[2]);
chkTriggerUrlUseAuthentication.setChecked(ActivityManageActionTriggerUrl.resultingAction.getParameter1());
etTriggerUrl.setText(components[2]);
chkTriggerUrlUseAuthentication.setChecked(getIntent().getBooleanExtra(ActivityManageRule.intentNameActionParameter1, false));
etTriggerUrlUsername.setText(components[0]);
etTriggerUrlPassword.setText(components[1]);
@@ -160,44 +203,56 @@ public class ActivityManageActionTriggerUrl extends Activity
break;
}
}
if(components.length >= 5)
{
if(!StringUtils.isEmpty(components[4]) && components[4].contains(Action.actionParameters2SeparatorInner))
{
String httpParams[] = components[4].split(Action.actionParameters2SeparatorOuter);
for (String paramPair : httpParams)
httpParamsList.add(paramPair);
updateHttpParamsList();
}
}
}
else
etTriggerUrl.setText(components[0]);
}
}
private void backToRuleManager()
{
if(edit && resultingAction != null)
bAddHttpParam.setOnClickListener(new OnClickListener()
{
String username = etTriggerUrlUsername.getText().toString();
String password = etTriggerUrlPassword.getText().toString();
if(username == null)
username = "";
if(password == null)
password = "";
@Override
public void onClick(View view)
{
if(StringUtils.isEmpty(etParameterName.getText()) || StringUtils.isEmpty(etParameterValue.getText()))
{
Toast.makeText(ActivityManageActionTriggerUrl.this, getResources().getString(R.string.enterValidDataIntoParametersFields), Toast.LENGTH_SHORT).show();
return;
}
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
httpParamsList.add(etParameterName.getText() + Action.actionParameters2SeparatorInner + etParameterValue.getText());
ActivityManageActionTriggerUrl.resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
ActivityManageActionTriggerUrl.resultingAction.setParameter2(
username + ";" +
password + ";" +
etTriggerUrl.getText().toString() + ";" +
method
);
}
setResult(RESULT_OK);
this.finish();
updateHttpParamsList();
etParameterName.setText("");
etParameterValue.setText("");
if(lvTriggerUrlPostParameters.getVisibility() != View.VISIBLE)
lvTriggerUrlPostParameters.setVisibility(View.VISIBLE);
}
});
lvTriggerUrlPostParameters.setOnItemLongClickListener(new OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
getHttpParamsDialog(arg2).show();
return false;
}
});
}
private void updateListView()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update lvTriggerUrlPostParameters", 4);
@@ -205,10 +260,36 @@ public class ActivityManageActionTriggerUrl extends Activity
{
if(lvTriggerUrlPostParameters.getAdapter() == null)
lvTriggerUrlPostParameters.setAdapter(lvTriggerUrlPostParametersAdapter);
lvTriggerUrlPostParametersAdapter.notifyDataSetChanged();
}
catch(NullPointerException e)
{}
}
private void updateHttpParamsList()
{
if(lvTriggerUrlPostParameters.getAdapter() == null)
lvTriggerUrlPostParameters.setAdapter(httpParametersAdapter);
httpParametersAdapter.notifyDataSetChanged();
}
private AlertDialog getHttpParamsDialog(final int itemPosition)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ActivityManageActionTriggerUrl.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
ActivityManageActionTriggerUrl.this.httpParamsList.remove(itemPosition);
updateHttpParamsList();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
}
@@ -2,10 +2,13 @@ package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.view.View;
@@ -22,12 +25,14 @@ public class ActivityManageActionVibrate extends Activity
{
TextView etVibratePattern;
Button bTestVibratePattern, bSaveVibratePattern;
ProgressDialog pdPleaseWait = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_vibrate);
etVibratePattern = (EditText)findViewById(R.id.etVibratePattern);
@@ -59,7 +64,20 @@ public class ActivityManageActionVibrate extends Activity
if (ActivityPermissions.havePermission(Manifest.permission.VIBRATE, ActivityManageActionVibrate.this))
{
String pattern = etVibratePattern.getText().toString();
Actions.vibrate(false, pattern);
String[] patternArray = pattern.split(",");
long sum = 0;
for(String element : patternArray)
sum += Long.parseLong(element);
if(sum <= 2000)
Actions.vibrate(false, pattern);
else
{
pdPleaseWait = ProgressDialog.show(ActivityManageActionVibrate.this, null, getResources().getString(R.string.pleaseWait));
VibrateTask vt = new VibrateTask();
vt.execute(pattern);
}
}
}
}
@@ -83,4 +101,22 @@ public class ActivityManageActionVibrate extends Activity
return true;
}
class VibrateTask extends AsyncTask<String, Void, Void>
{
@Override
protected Void doInBackground(String... strings)
{
String pattern = (String)strings[0];
Actions.vibrate(false, pattern);
return null;
}
@Override
protected void onPostExecute(Void unused)
{
pdPleaseWait.dismiss();
super.onPostExecute(unused);
}
}
}
@@ -28,6 +28,7 @@ public class ActivityManageActionWakeLock extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_wakelock);
rbWakeLockActivate = (RadioButton)findViewById(R.id.rbWakeLockActivate);
@@ -24,6 +24,7 @@ public class ActivityManageActionWifi extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_action_wifi);
chkWifiRunAsRoot = (CheckBox)findViewById(R.id.chkWifiRunAsRoot);
@@ -35,14 +36,14 @@ public class ActivityManageActionWifi extends Activity
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameActionParameter1))
{
rbActionWifiOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true));
rbActionWifiOff.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
@@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -7,6 +8,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
@@ -23,6 +25,9 @@ import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.PermissionChecker;
import com.jens.automation2.receivers.ConnectivityReceiver;
import java.util.Calendar;
@@ -40,6 +45,7 @@ public class ActivityManagePoi extends Activity
EditText guiPoiName, guiPoiLatitude, guiPoiLongitude, guiPoiRadius;
Calendar locationSearchStart = null;
Timer timer = null;
int requestCodeGetLocationPermission = 1293;
final static int defaultRadius = 250;
final static int searchTimeout = 120;
@@ -60,6 +66,7 @@ public class ActivityManagePoi extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_specific_poi);
myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
@@ -77,7 +84,15 @@ public class ActivityManagePoi extends Activity
public void onClick(View v)
{
hideKeyboard();
getNotificationDialog(getResources().getString(R.string.positioningWindowNotice)).show();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (ActivityPermissions.havePermission(Manifest.permission.ACCESS_FINE_LOCATION, ActivityManagePoi.this))
getNotificationDialog(getResources().getString(R.string.positioningWindowNotice)).show();
else
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, requestCodeGetLocationPermission);
}
else
getNotificationDialog(getResources().getString(R.string.positioningWindowNotice)).show();
}
});
@@ -111,7 +126,20 @@ public class ActivityManagePoi extends Activity
//else
// new Poi to be created
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if(requestCode == requestCodeGetLocationPermission)
{
if(permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION) && grantResults[0] == PackageManager.PERMISSION_GRANTED)
getNotificationDialog(getResources().getString(R.string.positioningWindowNotice)).show();
else
Toast.makeText(ActivityManagePoi.this, getResources().getString(R.string.locationPermissionRequired), Toast.LENGTH_LONG).show();
}
// super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void createPoi()
{
myLocationManager.removeUpdates(myLocationListenerGps);
@@ -314,20 +342,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
// 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();
}
};
@@ -411,22 +439,16 @@ public class ActivityManagePoi extends Activity
@Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
}
}
@@ -454,22 +476,16 @@ public class ActivityManagePoi extends Activity
@Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
}
}
@@ -1,7 +1,6 @@
package com.jens.automation2;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -28,8 +27,6 @@ import android.widget.Toast;
import androidx.annotation.RequiresApi;
import java.io.File;
public class ActivityManageProfile extends Activity
{
private static ProgressDialog progressDialog;
@@ -37,12 +34,13 @@ public class ActivityManageProfile extends Activity
final static int intentCodeRingtonePickerCallsRingtone = 9011;
final static int intentCodeRingtonePickerNotificationsFile = 9020;
final static int intentCodeRingtonePickerNotificationsRingtone = 9021;
final static String android14Hint = " (>= Android 14)";
CheckBox checkBoxChangeSoundMode, checkBoxChangeVolumeMusicVideoGameMedia, checkBoxChangeVolumeNotifications, checkBoxChangeVolumeAlarms, checkBoxChangeIncomingCallsRingtone, checkBoxChangeNotificationRingtone, checkBoxChangeAudibleSelection, checkBoxChangeScreenLockUnlockSound, checkBoxChangeHapticFeedback, checkBoxChangeVibrateWhenRinging, checkBoxVibrateWhenRinging, checkBoxAudibleSelection, checkBoxScreenLockUnlockSound, checkBoxHapticFeedback, checkBoxChangeDnd;
CheckBox checkBoxChangeSoundMode, checkBoxChangeVolumeMusicVideoGameMedia, checkBoxChangeVolumeNotifications, checkBoxChangeVolumeRingtone, checkBoxChangeVolumeAlarms, checkBoxChangeIncomingCallsRingtone, checkBoxChangeNotificationRingtone, checkBoxChangeAudibleSelection, checkBoxChangeScreenLockUnlockSound, checkBoxChangeHapticFeedback, checkBoxChangeVibrateWhenRinging, checkBoxVibrateWhenRinging, checkBoxAudibleSelection, checkBoxScreenLockUnlockSound, checkBoxHapticFeedback, checkBoxChangeDnd;
Spinner spinnerSoundMode, spinnerDndMode;
SeekBar seekBarVolumeMusic, seekBarVolumeNotifications, seekBarVolumeAlarms;
SeekBar seekBarVolumeMusic, seekBarVolumeNotifications, seekBarVolumeAlarms, seekBarVolumeRingtones;
Button bChangeSoundIncomingCalls, bChangeSoundNotifications, bSaveProfile;
TextView tvIncomingCallsRingtone, tvNotificationsRingtone;
TextView tvIncomingCallsRingtone, tvNotificationsRingtone, tvRingtoneVolume, tvNotificationsVolume;
EditText etName;
boolean guiUpdate = false;
@@ -87,12 +85,14 @@ public class ActivityManageProfile extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
this.setContentView(R.layout.activity_manage_specific_profile);
checkBoxChangeSoundMode = (CheckBox)findViewById(R.id.checkBoxChangeSoundMode);
checkBoxChangeDnd = (CheckBox)findViewById(R.id.checkBoxChangeDnd);
checkBoxChangeVolumeMusicVideoGameMedia = (CheckBox)findViewById(R.id.checkBoxChangeVolumeMusicVideoGameMedia);
checkBoxChangeVolumeNotifications = (CheckBox)findViewById(R.id.checkBoxChangeVolumeNotifications);
checkBoxChangeVolumeRingtone = (CheckBox)findViewById(R.id.checkBoxChangeVolumeRingtones);
checkBoxChangeVolumeAlarms = (CheckBox)findViewById(R.id.checkBoxChangeVolumeAlarms);
checkBoxChangeIncomingCallsRingtone = (CheckBox)findViewById(R.id.checkBoxChangeIncomingCallsRingtone);
checkBoxChangeNotificationRingtone = (CheckBox)findViewById(R.id.checkBoxChangeNotificationRingtone);
@@ -108,11 +108,14 @@ public class ActivityManageProfile extends Activity
spinnerDndMode = (Spinner)findViewById(R.id.spinnerDndMode);
seekBarVolumeMusic = (SeekBar)findViewById(R.id.seekBarVolumeMusic);
seekBarVolumeNotifications = (SeekBar)findViewById(R.id.seekBarVolumeNotifications);
seekBarVolumeRingtones = (SeekBar)findViewById(R.id.seekBarVolumeRingtones);
seekBarVolumeAlarms = (SeekBar)findViewById(R.id.seekBarVolumeAlarms);
bChangeSoundIncomingCalls = (Button)findViewById(R.id.bChangeSoundIncomingCalls);
bChangeSoundNotifications = (Button)findViewById(R.id.bChangeSoundNotifications);
tvIncomingCallsRingtone = (TextView)findViewById(R.id.tvIncomingCallsRingtone);
tvNotificationsRingtone = (TextView)findViewById(R.id.tvNotificationsRingtone);
tvRingtoneVolume = (TextView)findViewById(R.id.tvRingtoneVolume);
tvNotificationsVolume = (TextView)findViewById(R.id.tvNotificationsVolume);
bSaveProfile = (Button)findViewById(R.id.bSaveProfile);
etName = (EditText)findViewById(R.id.etName);
@@ -124,6 +127,7 @@ public class ActivityManageProfile extends Activity
spinnerDndMode.setEnabled(false);
seekBarVolumeMusic.setEnabled(false);
seekBarVolumeNotifications.setEnabled(false);
seekBarVolumeRingtones.setEnabled(false);
seekBarVolumeAlarms.setEnabled(false);
bChangeSoundIncomingCalls.setEnabled(false);
bChangeSoundNotifications.setEnabled(false);
@@ -137,11 +141,36 @@ public class ActivityManageProfile extends Activity
checkBoxChangeDnd.setEnabled(false);
spinnerDndMode.setEnabled(false);
}
if(Build.VERSION.SDK_INT >= 34)
{
checkBoxChangeVolumeRingtone.setEnabled(true);
checkBoxChangeVolumeRingtone.setVisibility(View.VISIBLE);
tvRingtoneVolume.setVisibility(View.VISIBLE);
seekBarVolumeRingtones.setVisibility(View.VISIBLE);
tvNotificationsVolume.setText(getResources().getString(R.string.volumeNotifications));
tvRingtoneVolume.setText(getResources().getString(R.string.volumeRingtone));
}
else
{
checkBoxChangeVolumeRingtone.setEnabled(false);
tvRingtoneVolume.setEnabled(false);
seekBarVolumeRingtones.setEnabled(false);
checkBoxChangeVolumeRingtone.setVisibility(View.GONE);
tvRingtoneVolume.setVisibility(View.GONE);
seekBarVolumeRingtones.setVisibility(View.GONE);
tvNotificationsVolume.setText(getResources().getString(R.string.volumeRingtone) + " + " + getResources().getString(R.string.volumeNotifications));
}
// Scale SeekBars to the system's maximum volume values
AudioManager am = (AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE);
seekBarVolumeMusic.setMax(am.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
seekBarVolumeNotifications.setMax(am.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION));
seekBarVolumeRingtones.setMax(am.getStreamMaxVolume(AudioManager.STREAM_RING));
seekBarVolumeAlarms.setMax(am.getStreamMaxVolume(AudioManager.STREAM_ALARM));
soundModeAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, new String[]
@@ -201,6 +230,14 @@ public class ActivityManageProfile extends Activity
seekBarVolumeNotifications.setEnabled(isChecked);
}
});
checkBoxChangeVolumeRingtone.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
seekBarVolumeRingtones.setEnabled(isChecked);
}
});
checkBoxChangeVolumeAlarms.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
@@ -336,7 +373,7 @@ public class ActivityManageProfile extends Activity
});
if(ActivityMainProfiles.profileToEdit != null)
editProfile(ActivityMainProfiles.profileToEdit);
loadValuesIntoGui(ActivityMainProfiles.profileToEdit);
//else
// new Profile to be created
@@ -369,7 +406,7 @@ public class ActivityManageProfile extends Activity
}
}
public void editProfile(Profile profileToEdit)
public void loadValuesIntoGui(Profile profileToEdit)
{
guiUpdate = true;
@@ -378,6 +415,7 @@ public class ActivityManageProfile extends Activity
checkBoxChangeDnd.setChecked(ActivityMainProfiles.profileToEdit.getChangeDndMode());
checkBoxChangeVolumeMusicVideoGameMedia.setChecked(ActivityMainProfiles.profileToEdit.getChangeVolumeMusicVideoGameMedia());
checkBoxChangeVolumeNotifications.setChecked(ActivityMainProfiles.profileToEdit.getChangeVolumeNotifications());
checkBoxChangeVolumeRingtone.setChecked(ActivityMainProfiles.profileToEdit.getChangeVolumeRingtones());
checkBoxChangeVolumeAlarms.setChecked(ActivityMainProfiles.profileToEdit.getChangeVolumeAlarms());
checkBoxChangeIncomingCallsRingtone.setChecked(ActivityMainProfiles.profileToEdit.getChangeIncomingCallsRingtone());
checkBoxChangeNotificationRingtone.setChecked(ActivityMainProfiles.profileToEdit.getChangeNotificationRingtone());
@@ -390,6 +428,7 @@ public class ActivityManageProfile extends Activity
spinnerDndMode.setSelection(ActivityMainProfiles.profileToEdit.getDndMode()-1);
seekBarVolumeMusic.setProgress(ActivityMainProfiles.profileToEdit.getVolumeMusic());
seekBarVolumeNotifications.setProgress(ActivityMainProfiles.profileToEdit.getVolumeNotifications());
seekBarVolumeRingtones.setProgress(ActivityMainProfiles.profileToEdit.getVolumeRingtones());
seekBarVolumeAlarms.setProgress(ActivityMainProfiles.profileToEdit.getVolumeAlarms());
checkBoxAudibleSelection.setChecked(ActivityMainProfiles.profileToEdit.audibleSelection);
checkBoxScreenLockUnlockSound.setChecked(ActivityMainProfiles.profileToEdit.screenLockUnlockSound);
@@ -414,6 +453,7 @@ public class ActivityManageProfile extends Activity
ActivityMainProfiles.profileToEdit.setChangeDndMode(checkBoxChangeDnd.isChecked());
ActivityMainProfiles.profileToEdit.setChangeVolumeMusicVideoGameMedia(checkBoxChangeVolumeMusicVideoGameMedia.isChecked());
ActivityMainProfiles.profileToEdit.setChangeVolumeNotifications(checkBoxChangeVolumeNotifications.isChecked());
ActivityMainProfiles.profileToEdit.setChangeVolumeRingtones(checkBoxChangeVolumeRingtone.isChecked());
ActivityMainProfiles.profileToEdit.setChangeVolumeAlarms(checkBoxChangeVolumeAlarms.isChecked());
ActivityMainProfiles.profileToEdit.setChangeIncomingCallsRingtone(checkBoxChangeIncomingCallsRingtone.isChecked());
ActivityMainProfiles.profileToEdit.setChangeNotificationRingtone(checkBoxChangeNotificationRingtone.isChecked());
@@ -430,6 +470,7 @@ public class ActivityManageProfile extends Activity
ActivityMainProfiles.profileToEdit.setDndMode(spinnerDndMode.getSelectedItemPosition()+1);
ActivityMainProfiles.profileToEdit.setVolumeMusic(seekBarVolumeMusic.getProgress());
ActivityMainProfiles.profileToEdit.setVolumeNotifications(seekBarVolumeNotifications.getProgress());
ActivityMainProfiles.profileToEdit.setVolumeRingtones(seekBarVolumeRingtones.getProgress());
ActivityMainProfiles.profileToEdit.setVolumeAlarms(seekBarVolumeAlarms.getProgress());
ActivityMainProfiles.profileToEdit.setIncomingCallsRingtone(incomingCallsRingtone);
ActivityMainProfiles.profileToEdit.setNotificationRingtone(notificationsRingtone);
@@ -145,6 +145,12 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionSetLocationServiceEdit = 832;
final static int requestCodeTriggerCalendarEventAdd = 833;
final static int requestCodeTriggerCalendarEventEdit = 834;
final static int requestCodeTriggerChargingAdd = 835;
final static int requestCodeTriggerChargingEdit = 836;
final static int requestCodeTriggerProximityAdd = 837;
final static int requestCodeTriggerProximityEdit = 838;
final static int requestCodeActionSetSystemSettingAdd = 839;
final static int requestCodeActionSetSystemSettingEdit = 840;
public static ActivityManageRule getInstance()
{
@@ -159,6 +165,7 @@ public class ActivityManageRule extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_specific_rule);
context = this;
@@ -355,6 +362,18 @@ public class ActivityManageRule extends Activity
calendarStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(calendarStateEditor, requestCodeTriggerCalendarEventEdit);
break;
case charging:
Intent chargingStateEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerCharging.class);
chargingStateEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
chargingStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(chargingStateEditor, requestCodeTriggerChargingEdit);
break;
case proximity:
Intent proximityEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerProximity.class);
proximityEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
proximityEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(proximityEditor, requestCodeTriggerProximityEdit);
break;
default:
break;
}
@@ -396,9 +415,8 @@ public class ActivityManageRule extends Activity
break;
case triggerUrl:
Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class);
ActivityManageActionTriggerUrl.resultingAction = a;
ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit);
activityEditTriggerUrlIntent.putExtra("edit", true);
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter1, a.getParameter1());
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit);
break;
case speakText:
@@ -494,6 +512,12 @@ public class ActivityManageRule extends Activity
actionSetLocationServiceIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(actionSetLocationServiceIntent, requestCodeActionSetLocationServiceEdit);
break;
case setSystemSetting:
Intent actionSetSystemSettingIntent = new Intent(context, ActivityManageActionSetSystemSetting.class);
// actionSetSystemSettingIntent.putExtra(intentNameActionParameter1, a.getParameter1());
actionSetSystemSettingIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(actionSetSystemSettingIntent, requestCodeActionSetSystemSettingEdit);
break;
default:
Miscellaneous.logEvent("w", "Edit action", "Editing of action type " + a.getAction().toString() + " not implemented, yet.", 4);
break;
@@ -534,7 +558,7 @@ public class ActivityManageRule extends Activity
public void onClick(View v)
{
// Open help popup
Miscellaneous.messageBox(getResources().getString(R.string.whatsThis), getResources().getString(R.string.helpTextToggable), ActivityManageRule.this).show();
Miscellaneous.messageBox(getResources().getString(R.string.whatsThis), getResources().getString(R.string.helpTextToggleable), ActivityManageRule.this).show();
}
});
}
@@ -615,7 +639,7 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString()))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, "android.permission.SEND_SMS"))
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
}
else if(types[i].toString().equals(Trigger_Enum.nfcTag.toString()))
@@ -647,7 +671,10 @@ public class ActivityManageRule extends Activity
else if(types[i].toString().equals(Trigger_Enum.checkVariable.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
else if(types[i].toString().equals(Trigger_Enum.calendarEvent.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.calendar));
{
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.READ_CALENDAR))
items.add(new Item(typesLong[i].toString(), R.drawable.calendar));
}
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@@ -708,7 +735,21 @@ public class ActivityManageRule extends Activity
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeAdd);
return;
}
else if(triggerType == Trigger_Enum.charging || triggerType == Trigger_Enum.musicPlaying)
else if(triggerType == Trigger_Enum.charging)
{
newTrigger.setTriggerType(Trigger_Enum.charging);
Intent triggerChargingIntent = new Intent(myContext, ActivityManageTriggerCharging.class);
startActivityForResult(triggerChargingIntent, requestCodeTriggerChargingAdd);
return;
}
else if(triggerType == Trigger_Enum.proximity)
{
newTrigger.setTriggerType(Trigger_Enum.proximity);
Intent triggerProximityIntent = new Intent(myContext, ActivityManageTriggerProximity.class);
startActivityForResult(triggerProximityIntent, requestCodeTriggerProximityAdd);
return;
}
else if(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)};
@@ -1382,9 +1423,11 @@ public class ActivityManageRule extends Activity
{
if(resultCode == RESULT_OK)
{
//add TriggerUrl
ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit);
ruleToEdit.getActionSet().add(ActivityManageActionTriggerUrl.resultingAction);
newAction.setParentRule(ruleToEdit);
newAction.setAction(Action_Enum.triggerUrl);
newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, true));
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
@@ -1392,7 +1435,14 @@ public class ActivityManageRule extends Activity
{
if(resultCode == RESULT_OK)
{
//edit TriggerUrl
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
if(data.hasExtra(intentNameActionParameter1))
ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, true));
if(data.hasExtra(intentNameActionParameter2))
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
this.refreshActionList();
}
}
@@ -1449,6 +1499,54 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerChargingAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerProximityAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerChargingEdit)
{
if(resultCode == RESULT_OK)
{
Trigger chargingStateTrigger = new Trigger();
chargingStateTrigger.setTriggerType(Trigger_Enum.charging);
chargingStateTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
chargingStateTrigger.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
chargingStateTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, chargingStateTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerProximityEdit)
{
if(resultCode == RESULT_OK)
{
Trigger proximityTrigger = new Trigger();
proximityTrigger.setTriggerType(Trigger_Enum.proximity);
proximityTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
proximityTrigger.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
proximityTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, proximityTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeActionStartActivityAdd)
{
// manage start of other activity
@@ -2127,6 +2225,32 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionSetSystemSettingAdd)
{
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 == requestCodeActionSetSystemSettingEdit)
{
if(resultCode == RESULT_OK)
{
ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit);
// ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, false));
if(data.hasExtra(intentNameActionParameter2))
{
ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2));
}
this.refreshActionList();
}
}
}
protected AlertDialog getActionTypeDialog()
@@ -2188,27 +2312,33 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.script));
else if(types[i].toString().equals(Action_Enum.startPhoneCall.toString()))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.CALL_PHONE))
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.CALL_PHONE))
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
}
else if(types[i].toString().equals(Action_Enum.stopPhoneCall.toString()))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.ANSWER_PHONE_CALLS))
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.ANSWER_PHONE_CALLS))
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
}
else if(types[i].toString().equals(Action_Enum.sendTextMessage.toString()))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
items.add(new Item(typesLong[i].toString(), R.drawable.message));
}
else if(types[i].toString().equals(Action_Enum.copyToClipboard.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.clipboard));
else if(types[i].toString().equals(Action_Enum.takeScreenshot.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.copier));
else if(types[i].toString().equals(Action_Enum.setVariable.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
else if(types[i].toString().equals(Action_Enum.setLocationService.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.compass_small));
else if(types[i].toString().equals(Action_Enum.takeScreenshot.toString()))
{
if(ActivityPermissions.isServiceAvailable(Miscellaneous.getAnyContext(), "MyAccessibilityService"))
items.add(new Item(typesLong[i].toString(), R.drawable.copier));
}
else if(types[i].toString().equals(Action_Enum.setSystemSetting.toString()))
{ items.add(new Item(typesLong[i].toString(), R.drawable.gears_small));
}
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@@ -2241,28 +2371,28 @@ public class ActivityManageRule extends Activity
{
newAction = new Action();
if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.triggerUrl.toString()))
CharSequence[] actionTypes = Action.getActionTypesAsArray();
if(actionTypes[which].toString().equals(Action_Enum.triggerUrl.toString()))
{
//launch other activity to enter a url and parameters;
newAction.setAction(Action_Enum.triggerUrl);
ActivityManageActionTriggerUrl.resultingAction = null;
Intent editTriggerIntent = new Intent(context, ActivityManageActionTriggerUrl.class);
startActivityForResult(editTriggerIntent, requestCodeActionTriggerUrlAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setWifi.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setWifi.toString()))
{
newAction.setAction(Action_Enum.setWifi);
Intent editSetWifiIntent = new Intent(context, ActivityManageActionWifi.class);
startActivityForResult(editSetWifiIntent, requestCodeActionSetWifiAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setBluetooth.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setBluetooth.toString()))
{
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH))
Miscellaneous.messageBox("Bluetooth", getResources().getString(R.string.deviceDoesNotHaveBluetooth), ActivityManageRule.this).show();;
newAction.setAction(Action_Enum.setBluetooth);
getActionParameter1Dialog(ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setUsbTethering.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setUsbTethering.toString()))
{
newAction.setAction(Action_Enum.setUsbTethering);
getActionParameter1Dialog(ActivityManageRule.this).show();
@@ -2270,12 +2400,12 @@ public class ActivityManageRule extends Activity
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1)
Miscellaneous.messageBox(context.getResources().getString(R.string.warning), context.getResources().getString(R.string.usbTetheringFailForAboveGingerbread), context).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setWifiTethering.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setWifiTethering.toString()))
{
newAction.setAction(Action_Enum.setWifiTethering);
getActionParameter1Dialog(ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setBluetoothTethering.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setBluetoothTethering.toString()))
{
newAction.setAction(Action_Enum.setBluetoothTethering);
getActionParameter1Dialog(ActivityManageRule.this).show();
@@ -2286,12 +2416,12 @@ public class ActivityManageRule extends Activity
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
Miscellaneous.messageBox(context.getResources().getString(R.string.notice), context.getResources().getString(R.string.btTetheringNotice), context).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setDisplayRotation.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setDisplayRotation.toString()))
{
newAction.setAction(Action_Enum.setDisplayRotation);
getActionParameter1Dialog(ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.changeSoundProfile.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.changeSoundProfile.toString()))
{
if(Profile.getProfileCollection().size() > 0)
{
@@ -2301,23 +2431,23 @@ public class ActivityManageRule extends Activity
else
Toast.makeText(context, getResources().getString(R.string.noProfilesCreateOneFirst), Toast.LENGTH_LONG).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.startOtherActivity.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.startOtherActivity.toString()))
{
newAction.setAction(Action_Enum.startOtherActivity);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionStartActivity.class);
startActivityForResult(intent, requestCodeActionStartActivityAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.waitBeforeNextAction.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.waitBeforeNextAction.toString()))
{
newAction.setAction(Action_Enum.waitBeforeNextAction);
getActionWaitBeforeNextActionDialog(ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.turnScreenOnOrOff.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.turnScreenOnOrOff.toString()))
{
newAction.setAction(Action_Enum.turnScreenOnOrOff);
getActionParameter1Dialog(ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setAirplaneMode.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setAirplaneMode.toString()))
{
newAction.setAction(Action_Enum.setAirplaneMode);
getActionParameter1Dialog(ActivityManageRule.this).show();
@@ -2326,13 +2456,13 @@ public class ActivityManageRule extends Activity
Miscellaneous.messageBox(getResources().getString(R.string.airplaneMode), getResources().getString(R.string.rootExplanation), ActivityManageRule.this).show();
}
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setDataConnection.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setDataConnection.toString()))
{
newAction.setAction(Action_Enum.setDataConnection);
getActionParameter1Dialog(ActivityManageRule.this).show();
Miscellaneous.messageBox(getResources().getString(R.string.actionDataConnection), getResources().getString(R.string.rootExplanation), ActivityManageRule.this).show();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.speakText.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.speakText.toString()))
{
//launch other activity to enter a url and parameters;
newAction.setAction(Action_Enum.speakText);
@@ -2340,9 +2470,9 @@ public class ActivityManageRule extends Activity
Intent editTriggerIntent = new Intent(context, ActivityManageActionSpeakText.class);
startActivityForResult(editTriggerIntent, requestCodeActionSpeakTextAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.sendTextMessage.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.sendTextMessage.toString()))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
{
//launch other activity to enter parameters;
newAction.setAction(Action_Enum.sendTextMessage);
@@ -2351,102 +2481,108 @@ public class ActivityManageRule extends Activity
startActivityForResult(editTriggerIntent, requestCodeActionSendTextMessageAdd);
}
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.playMusic.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.playMusic.toString()))
{
newAction.setAction(Action_Enum.playMusic);
ruleToEdit.getActionSet().add(newAction);
refreshActionList();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.vibrate.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.vibrate.toString()))
{
newAction.setAction(Action_Enum.vibrate);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionVibrate.class);
startActivityForResult(intent, requestCodeActionVibrateAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.sendBroadcast.toString()))
else if(actionTypes[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()))
else if(actionTypes[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.startPhoneCall.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.startPhoneCall.toString()))
{
newAction.setAction(Action_Enum.startPhoneCall);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionMakePhoneCall.class);
startActivityForResult(intent, requestCodeActionMakePhoneCallAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setVariable.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setVariable.toString()))
{
newAction.setAction(Action_Enum.setVariable);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionSetVariable.class);
startActivityForResult(intent, requestCodeActionSetVariableAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.stopPhoneCall.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.stopPhoneCall.toString()))
{
newAction.setAction(Action_Enum.stopPhoneCall);
ruleToEdit.getActionSet().add(newAction);
refreshActionList();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.wakelock.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.wakelock.toString()))
{
newAction.setAction(Action_Enum.wakelock);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionWakeLock.class);
startActivityForResult(intent, requestCodeActionWakeLockAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString()))
else if(actionTypes[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()))
else if(actionTypes[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()))
else if(actionTypes[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()))
else if(actionTypes[which].toString().equals(Action_Enum.setScreenBrightness.toString()))
{
newAction.setAction(Action_Enum.setScreenBrightness);
Intent actionScreenBrightnessIntent = new Intent(context, ActivityManageActionBrightnessSetting.class);
startActivityForResult(actionScreenBrightnessIntent, requestCodeActionScreenBrightnessAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.playSound.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.playSound.toString()))
{
newAction.setAction(Action_Enum.playSound);
Intent actionPlaySoundIntent = new Intent(context, ActivityManageActionPlaySound.class);
startActivityForResult(actionPlaySoundIntent, requestCodeActionPlaySoundAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.copyToClipboard.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.copyToClipboard.toString()))
{
newAction.setAction(Action_Enum.copyToClipboard);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCopyToClipboard.class);
startActivityForResult(intent, requestCodeActionCopyTextToClipboardAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.takeScreenshot.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.takeScreenshot.toString()))
{
newAction.setAction(Action_Enum.takeScreenshot);
ruleToEdit.getActionSet().add(newAction);
refreshActionList();
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setLocationService.toString()))
else if(actionTypes[which].toString().equals(Action_Enum.setLocationService.toString()))
{
newAction.setAction(Action_Enum.setLocationService);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionLocationService.class);
startActivityForResult(intent, requestCodeActionSetLocationServiceAdd);
}
else if(actionTypes[which].toString().equals(Action_Enum.setSystemSetting.toString()))
{
newAction.setAction(Action_Enum.setSystemSetting);
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionSetSystemSetting.class);
startActivityForResult(intent, requestCodeActionSetSystemSettingAdd);
}
}
});
@@ -1,8 +1,10 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -16,23 +18,27 @@ import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.jens.automation2.receivers.BluetoothReceiver;
public class ActivityManageTriggerBluetooth extends Activity
{
final static int requestPermissionCodeBluetoothConnect = 4711;
protected static Trigger editedBluetoothTrigger;
RadioButton radioAnyBluetoothDevice, radioNoDevice, radioDeviceFromList, radioBluetoothConnected, radioBluetoothDisconnected, radioBluetoothInRange, radioBluetoothOutRange;
Button bSaveBluetoothTrigger;
Spinner spinnerBluetoothDevices;
TextView tvBluetoothNotPresentNotice;
ArrayAdapter<String> bluetoothDevicesSpinnerAdapter;
ArrayAdapter<String> bluetoothDevicesSpinnerAdapter = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_bluetooth);
radioAnyBluetoothDevice = (RadioButton)findViewById(R.id.radioAnyBluetoothDevice);
@@ -45,8 +51,6 @@ public class ActivityManageTriggerBluetooth extends Activity
bSaveBluetoothTrigger = (Button)findViewById(R.id.bSaveBluetoothTrigger);
spinnerBluetoothDevices = (Spinner)findViewById(R.id.spinnerBluetoothDevices);
tvBluetoothNotPresentNotice = (TextView)findViewById(R.id.tvBluetoothNotPresentNotice);
bluetoothDevicesSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, BluetoothReceiver.getAllPairedBluetoothDevicesStrings());
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH))
tvBluetoothNotPresentNotice.setVisibility(View.VISIBLE);
@@ -74,17 +78,37 @@ public class ActivityManageTriggerBluetooth extends Activity
}
}
});
refreshBluetoothDeviceSpinner();
spinnerBluetoothDevices.setEnabled(false);
if(Miscellaneous.getTargetSDK(ActivityManageTriggerBluetooth.this) >= 31 && !ActivityPermissions.havePermission(Manifest.permission.BLUETOOTH_CONNECT, ActivityManageTriggerBluetooth.this))
requestPermissions(new String[] {Manifest.permission.BLUETOOTH_CONNECT }, requestPermissionCodeBluetoothConnect);
else
refreshBluetoothDeviceSpinner();
spinnerBluetoothDevices.setEnabled(false);
if(editedBluetoothTrigger.getBluetoothDeviceAddress() != null && editedBluetoothTrigger.getBluetoothDeviceAddress().length() > 0)
loadVariableIntoGui();
}
protected void refreshBluetoothDeviceSpinner()
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == requestPermissionCodeBluetoothConnect)
{
if(permissions[0].equals(Manifest.permission.BLUETOOTH_CONNECT) && grantResults[0] == PackageManager.PERMISSION_GRANTED)
refreshBluetoothDeviceSpinner();
}
}
protected void refreshBluetoothDeviceSpinner()
{
Miscellaneous.logEvent("i", "Spinner", "Attempting to update spinnerBluetoothDevices", 4);
if(bluetoothDevicesSpinnerAdapter == null)
bluetoothDevicesSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, BluetoothReceiver.getAllPairedBluetoothDevicesStrings());
if(spinnerBluetoothDevices.getAdapter() == null)
{
spinnerBluetoothDevices.setAdapter(bluetoothDevicesSpinnerAdapter);
@@ -29,6 +29,7 @@ public class ActivityManageTriggerBroadcast extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_broadcasts);
bBroadcastShowSuggestions = findViewById(R.id.bBroadcastShowSuggestions);
@@ -9,6 +9,7 @@ import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
@@ -18,6 +19,7 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -31,7 +33,7 @@ import java.util.List;
public class ActivityManageTriggerCalendar extends Activity
{
CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent;
CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent, chkCalendarEvaluateAllDayEvent, chkCalendarEvaluateReoccurring, chkCalendarReoccurring;
Spinner spinnerCalendarTitleDirection, spinnerCalendarLocationDirection, spinnerCalendarDescriptionDirection;
EditText etCalendarTitle, etCalendarLocation, etCalendarDescription;
LinearLayout llCalendarSelection;
@@ -49,6 +51,7 @@ public class ActivityManageTriggerCalendar extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_calendar);
chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive);
@@ -61,6 +64,9 @@ public class ActivityManageTriggerCalendar extends Activity
chkCalendarAvailabilityTentative = (CheckBox)findViewById(R.id.chkCalendarAvailabilityTentative);
chkCalendarAvailabilityOutOfOffice = (CheckBox)findViewById(R.id.chkCalendarAvailabilityOutOfOffice);
chkCalendarAvailabilityWorkingElsewhere = (CheckBox)findViewById(R.id.chkCalendarAvailabilityWorkingElsewhere);
chkCalendarEvaluateAllDayEvent = (CheckBox)findViewById(R.id.chkCalendarEvaluateAllDayEvent);
chkCalendarEvaluateReoccurring = (CheckBox)findViewById(R.id.chkCalendarEvaluateReoccurring);
chkCalendarReoccurring = (CheckBox)findViewById(R.id.chkCalendarReoccurring);
tvMissingCalendarHint = (TextView) findViewById(R.id.tvMissingCalendarHint);
@@ -80,12 +86,34 @@ public class ActivityManageTriggerCalendar extends Activity
getResources().getString(R.string.directionStringEndsWith),
getResources().getString(R.string.directionStringNotEquals)
};
directionSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageTriggerCalendar.directions);
directionSpinnerAdapter = new ArrayAdapter<>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageTriggerCalendar.directions);
spinnerCalendarTitleDirection.setAdapter(directionSpinnerAdapter);
spinnerCalendarLocationDirection.setAdapter(directionSpinnerAdapter);
spinnerCalendarDescriptionDirection.setAdapter(directionSpinnerAdapter);
directionSpinnerAdapter.notifyDataSetChanged();
chkCalendarEvaluateAllDayEvent.setChecked(false);
chkCalendarAllDayEvent.setEnabled(false);
chkCalendarEvaluateAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
chkCalendarAllDayEvent.setEnabled(checked);
}
});
chkCalendarEvaluateReoccurring.setChecked(false);
chkCalendarReoccurring.setEnabled(false);
chkCalendarEvaluateReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
chkCalendarReoccurring.setEnabled(checked);
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, ActivityManageTriggerCalendar.this) || ActivityPermissions.havePermission(Manifest.permission.WRITE_CALENDAR, ActivityManageTriggerCalendar.this))
@@ -141,6 +169,18 @@ public class ActivityManageTriggerCalendar extends Activity
}
});
chkCalendarReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
if(checked)
chkCalendarReoccurring.setText(R.string.reoccurringTrue);
else
chkCalendarReoccurring.setText(R.string.reoccurringFalse);
}
});
bSaveTriggerCalendar.setOnClickListener(new View.OnClickListener()
{
@Override
@@ -183,7 +223,10 @@ public class ActivityManageTriggerCalendar extends Activity
titleDir + Trigger.triggerParameter2Split + title + Trigger.triggerParameter2Split +
descriptionDir + Trigger.triggerParameter2Split + description + Trigger.triggerParameter2Split +
locationDir + Trigger.triggerParameter2Split + location + Trigger.triggerParameter2Split +
String.valueOf(chkCalendarEvaluateAllDayEvent.isChecked()) + Trigger.triggerParameter2Split +
String.valueOf(chkCalendarAllDayEvent.isChecked()) + Trigger.triggerParameter2Split +
String.valueOf(chkCalendarEvaluateReoccurring.isChecked()) + Trigger.triggerParameter2Split +
String.valueOf(chkCalendarReoccurring.isChecked()) + Trigger.triggerParameter2Split +
Miscellaneous.explode(separator, availabilityList.toArray(new String[availabilityList.size()])) + Trigger.triggerParameter2Split +
Miscellaneous.explode(separator, selectedCalendarsIdArray.toArray(new String[selectedCalendarsIdArray.size()]));
@@ -227,14 +270,14 @@ public class ActivityManageTriggerCalendar extends Activity
void loadValuesIntoGui(Intent data)
{
//TODO:try-catch
if(data.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
chkCalendarEventActive.setChecked(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
if(data.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
try
{
String input[] = data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split, -1);
if (data.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
chkCalendarEventActive.setChecked(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
if (data.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
String input[] = data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split, -1);
/*
0 = titleDir
1 = title
@@ -242,88 +285,101 @@ public class ActivityManageTriggerCalendar extends Activity
3 = description
4 = locationDir
5 = location
6 = all day event
7 = availability list
8 = calendars list
6 = evaluate all day event
7 = all day event
8 = evaluate reoccurring
9 = reoccurring
10 = availability list
11 = calendars list
*/
for(int i = 0; i < directions.length; i++)
{
if(Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[0]))
spinnerCalendarTitleDirection.setSelection(i);
if(Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[2]))
spinnerCalendarDescriptionDirection.setSelection(i);
if(Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[4]))
spinnerCalendarLocationDirection.setSelection(i);
}
etCalendarTitle.setText(input[1]);
etCalendarDescription.setText(input[3]);
etCalendarLocation.setText(input[5]);
chkCalendarAllDayEvent.setChecked(Boolean.parseBoolean(input[6]));
String[] availabilities = null;
if(!StringUtils.isEmpty(input[7]))
availabilities = input[7].split(separator);
if(availabilities != null)
{
for (String avail : availabilities)
for (int i = 0; i < directions.length; i++)
{
if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_BUSY)
chkCalendarAvailabilityBusy.setChecked(true);
else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_FREE)
chkCalendarAvailabilityFree.setChecked(true);
else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_TENTATIVE)
chkCalendarAvailabilityTentative.setChecked(true);
else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE)
chkCalendarAvailabilityOutOfOffice.setChecked(true);
else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE)
chkCalendarAvailabilityWorkingElsewhere.setChecked(true);
if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[0]))
spinnerCalendarTitleDirection.setSelection(i);
if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[2]))
spinnerCalendarDescriptionDirection.setSelection(i);
if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[4]))
spinnerCalendarLocationDirection.setSelection(i);
}
}
String[] calendars = null;
if(!StringUtils.isEmpty(input[8]))
calendars = input[8].split(separator);
etCalendarTitle.setText(input[1]);
etCalendarDescription.setText(input[3]);
etCalendarLocation.setText(input[5]);
if(calendars != null)
{
List<String> usedCalendarIDs = new ArrayList<>();
List<String> unusedCalendarIDs = new ArrayList<>();
for (CheckBox checkbox : checkboxesCalendars)
chkCalendarEvaluateAllDayEvent.setChecked(Boolean.parseBoolean(input[6]));
chkCalendarAllDayEvent.setChecked(Boolean.parseBoolean(input[7]));
chkCalendarEvaluateReoccurring.setChecked(Boolean.parseBoolean(input[8]));
chkCalendarReoccurring.setChecked(Boolean.parseBoolean(input[9]));
String[] availabilities = null;
if (!StringUtils.isEmpty(input[10]))
availabilities = input[10].split(separator);
if (availabilities != null)
{
int id = ((CalendarReceiver.AndroidCalendar) checkbox.getTag()).calendarId;
for (String calId : calendars)
for (String avail : availabilities)
{
if (calId.equals(String.valueOf(id)))
{
usedCalendarIDs.add(String.valueOf(id));
checkbox.setChecked(true);
break;
}
if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_BUSY)
chkCalendarAvailabilityBusy.setChecked(true);
else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_FREE)
chkCalendarAvailabilityFree.setChecked(true);
else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_TENTATIVE)
chkCalendarAvailabilityTentative.setChecked(true);
else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE)
chkCalendarAvailabilityOutOfOffice.setChecked(true);
else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE)
chkCalendarAvailabilityWorkingElsewhere.setChecked(true);
}
}
for (String calId : calendars)
{
if (!Miscellaneous.arraySearch((ArrayList<String>) usedCalendarIDs, calId, false, true))
unusedCalendarIDs.add(calId);
}
if (unusedCalendarIDs.size() > 0)
String[] calendars = null;
if (!StringUtils.isEmpty(input[11]))
calendars = input[11].split(separator);
if (calendars != null)
{
List<String> usedCalendarIDs = new ArrayList<>();
List<String> unusedCalendarIDs = new ArrayList<>();
for (CheckBox checkbox : checkboxesCalendars)
{
int id = ((CalendarReceiver.AndroidCalendar) checkbox.getTag()).calendarId;
for (String calId : calendars)
{
if (calId.equals(String.valueOf(id)))
{
usedCalendarIDs.add(String.valueOf(id));
checkbox.setChecked(true);
break;
}
}
}
for (String calId : calendars)
{
if (!Miscellaneous.arraySearch((ArrayList<String>) usedCalendarIDs, calId, false, true))
unusedCalendarIDs.add(calId);
}
if (unusedCalendarIDs.size() > 0)
{
/*
A calendar has been configured that has been deleted since. We cannot resolve it.
It will be removed with the next save, but we should inform this user
of these circumstances.
*/
tvMissingCalendarHint.setText(String.format(getResources().getString(R.string.calendarsMissingHint), Miscellaneous.explode(", ", (ArrayList<String>) unusedCalendarIDs)));
tvMissingCalendarHint.setText(String.format(getResources().getString(R.string.calendarsMissingHint), Miscellaneous.explode(", ", (ArrayList<String>) unusedCalendarIDs)));
}
}
}
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "ActivityManagerTriggerCalender", "Error loading values into GUI: " + Log.getStackTraceString(e), 1);
Toast.makeText(ActivityManageTriggerCalendar.this, getResources().getString(R.string.errorLoadingValues), Toast.LENGTH_SHORT).show();
}
}
@Override
@@ -0,0 +1,83 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.BatteryManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import androidx.annotation.Nullable;
import com.jens.automation2.receivers.BatteryReceiver;
public class ActivityManageTriggerCharging extends Activity
{
RadioButton rbChargingOn, rbChargingOff, rbChargingTypeAny, rbChargingTypeAc, rbChargingTypeUsb, rbChargingTypeWireless;
Button bTriggerChargingSave;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_charging);
rbChargingOn = (RadioButton) findViewById(R.id.rbChargingOn);
rbChargingOff = (RadioButton) findViewById(R.id.rbChargingOff);
rbChargingTypeAny = (RadioButton) findViewById(R.id.rbChargingTypeAny);
rbChargingTypeAc = (RadioButton) findViewById(R.id.rbChargingTypeAc);
rbChargingTypeUsb = (RadioButton) findViewById(R.id.rbChargingTypeUsb);
rbChargingTypeWireless = (RadioButton) findViewById(R.id.rbChargingTypeWireless);
bTriggerChargingSave = (Button) findViewById(R.id.bTriggerChargingSave);
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
{
rbChargingOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
rbChargingOff.setChecked(!input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
String[] params2 = input.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split);
int chargingType = Integer.parseInt(params2[0]);
rbChargingTypeAny.setChecked(chargingType == 0);
rbChargingTypeAc.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_AC);
rbChargingTypeUsb.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_USB);
rbChargingTypeWireless.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_WIRELESS);
}
}
bTriggerChargingSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbChargingOn.isChecked());
String param2 = "";
if(rbChargingTypeAny.isChecked())
param2 = String.valueOf(BatteryReceiver.batteryChargingTypeAny);
else if(rbChargingTypeAc.isChecked())
param2 = String.valueOf(BatteryReceiver.batteryChargingTypeAc);
else if(rbChargingTypeUsb.isChecked())
param2 = String.valueOf(BatteryReceiver.batteryChargingTypeUsb);
else if(rbChargingTypeWireless.isChecked())
param2 = String.valueOf(BatteryReceiver.batteryChargingTypeWireless);
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, param2);
setResult(RESULT_OK, response);
finish();
}
});
}
}
@@ -5,6 +5,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import androidx.annotation.Nullable;
@@ -14,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
public class ActivityManageTriggerCheckVariable extends Activity
{
EditText etVariableKeyTrigger, etVariableValueTrigger;
CheckBox chkTriggerVariableDirection;
Button bTriggerVariableSave;
@Override
@@ -21,13 +24,19 @@ public class ActivityManageTriggerCheckVariable extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_check_variable);
etVariableKeyTrigger = (EditText) findViewById(R.id.etVariableKeyTrigger);
etVariableValueTrigger = (EditText) findViewById(R.id.etVariableValueTrigger);
chkTriggerVariableDirection = (CheckBox)findViewById(R.id.chkTriggerVariableDirection);
bTriggerVariableSave = (Button) findViewById(R.id.bTriggerVariableSave);
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
chkTriggerVariableDirection.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
String[] conditions = input.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split);
@@ -36,13 +45,26 @@ public class ActivityManageTriggerCheckVariable extends Activity
etVariableValueTrigger.setText(conditions[1]);
}
chkTriggerVariableDirection.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
if(checked)
chkTriggerVariableDirection.setText(getResources().getString(R.string.matches));
else
chkTriggerVariableDirection.setText(getResources().getString(R.string.doesNotMatch));
}
});
bTriggerVariableSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent response = new Intent();
// response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbTetheringOn.isChecked());
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, chkTriggerVariableDirection.isChecked());
if(StringUtils.isEmpty(etVariableValueTrigger.getText().toString()))
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, etVariableKeyTrigger.getText().toString());
@@ -105,6 +105,7 @@ public class ActivityManageTriggerDeviceOrientation extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_device_orientation);
currentAzimuth = (TextView) findViewById(R.id.tvCurrentAzimuth);
@@ -40,6 +40,7 @@ public class ActivityManageTriggerNfc extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_nfc);
etNewNfcIdValue = (EditText)findViewById(R.id.etNewNfcIdValue);
@@ -150,7 +151,12 @@ public class ActivityManageTriggerNfc extends Activity
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
final PendingIntent pendingIntent;
if(Miscellaneous.getTargetSDK(activity) >= 31)
pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE);
else
pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
@@ -185,7 +191,7 @@ public class ActivityManageTriggerNfc extends Activity
@Override
protected void onPause()
{
/**
/*
* Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
*/
disableForegroundDispatch(this);
@@ -197,7 +203,7 @@ public class ActivityManageTriggerNfc extends Activity
protected void onResume()
{
super.onResume();
/**
/*
* It's important, that the activity is in the foreground (resumed). Otherwise
* an IllegalStateException is thrown.
*/
@@ -231,10 +237,18 @@ public class ActivityManageTriggerNfc extends Activity
if(currentStatus == 0)
{
generatedId = NfcReceiver.readTag(discoveredTag);
if(generatedId != null && generatedId.length() > 0)
tvCurrentNfcId.setText(generatedId);
if(generatedId != null && generatedId.length() > 0)
{
tvCurrentNfcId.setText(generatedId);
bReadNfcTag.setEnabled(true);
bUseValueCurrentlyStored.setEnabled(true);
}
else
tvCurrentNfcId.setText(getResources().getString(R.string.nfcTagDataNotUsable));
{
tvCurrentNfcId.setText(getResources().getString(R.string.nfcTagDataNotUsable));
bReadNfcTag.setEnabled(false);
bUseValueCurrentlyStored.setEnabled(false);
}
}
else if(currentStatus == 1)
{
@@ -259,6 +259,7 @@ public class ActivityManageTriggerNotification extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_notification);
etNotificationTitle = (EditText)findViewById(R.id.etNotificationTitle);
@@ -36,6 +36,7 @@ public class ActivityManageTriggerPhoneCall extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_phone_call);
etTriggerPhoneCallPhoneNumber = (EditText)findViewById(R.id.etTriggerPhoneCallPhoneNumber);
@@ -32,6 +32,7 @@ public class ActivityManageTriggerProfile extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_profile);
bSaveTriggerProfile = (Button)findViewById(R.id.bSaveTriggerProfile);
@@ -0,0 +1,172 @@
package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import com.google.android.material.slider.RangeSlider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ActivityManageTriggerProximity extends Activity
{
TextView tvTriggerProximityHint, tvProximityCurrentValue;
Button bTriggerProximitySave;
RangeSlider rsProximity;
SeekBar sbProximityTest;
SensorManager sensorManager;
Sensor proximitySensor;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
/*
A modern theme is required for this activity because of the RangeSlider.
The value configured in settings is ignored.
*/
this.setTheme(R.style.AppThemeMaterial);
setContentView(R.layout.activity_manage_trigger_proximity);
rsProximity = (RangeSlider) findViewById(R.id.rsProximity);
sbProximityTest = (SeekBar) findViewById(R.id.sbProximityTest);
tvTriggerProximityHint = (TextView) findViewById(R.id.tvTriggerProximityHint);
tvProximityCurrentValue = (TextView) findViewById(R.id.tvProximityCurrentValue);
bTriggerProximitySave = (Button) findViewById(R.id.bTriggerProximitySave);
sbProximityTest.setEnabled(false);
tvTriggerProximityHint.setVisibility(View.GONE);
bTriggerProximitySave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, String.valueOf(rsProximity.getValues().get(0)) + Trigger.triggerParameter2Split + String.valueOf(rsProximity.getValues().get(1)));
setResult(RESULT_OK, response);
finish();
}
});
if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
String[] values = getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split);
rsProximity.setValues(Float.parseFloat(values[0]), Float.parseFloat(values[1]));
}
else
rsProximity.setValues(0f, 10f);
}
@Override
protected void onResume()
{
super.onResume();
startPreview();
}
@Override
protected void onPause()
{
super.onPause();
stopPreview();
}
void startPreview()
{
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// from sensor service we are
// calling proximity sensor
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
// handling the case if the proximity
// sensor is not present in users device.
if (proximitySensor == null)
{
tvTriggerProximityHint.setVisibility(View.VISIBLE);
finish();
}
else
{
// registering our sensor with sensor manager.
sensorManager.registerListener(proximitySensorEventListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
void stopPreview()
{
if(proximitySensor != null)
sensorManager.unregisterListener(proximitySensorEventListener);
}
SensorEventListener proximitySensorEventListener = new SensorEventListener()
{
@Override
public void onSensorChanged(SensorEvent sensorEvent)
{
// check if the sensor type is proximity sensor.
if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY)
{
sbProximityTest.setProgress((int)sensorEvent.values[0]);
tvProximityCurrentValue.setText((String.valueOf(sensorEvent.values[0])));
// if (sensorEvent.values[0] == 0)
// {
// here we are setting our status to our textview..
// if sensor event return 0 then object is closed
// to sensor else object is away from sensor.
// sensorStatusTV.setText("Near");
// }
// else
// {
// sensorStatusTV.setText("Away");
// }
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i)
{
}
};
}
@@ -22,6 +22,7 @@ public class ActivityManageTriggerSubSystemState extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_subsystemstate);
rbSubSystemStateWifi = (RadioButton)findViewById(R.id.rbSubSystemStateWifi);
@@ -27,6 +27,7 @@ public class ActivityManageTriggerTethering extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_tethering);
rbTetheringOn = (RadioButton) findViewById(R.id.rbTetheringOn);
@@ -2,6 +2,7 @@ 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.view.View.OnClickListener;
@@ -36,12 +37,22 @@ public class ActivityManageTriggerTimeFrame extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
/*
A modern theme is required for this activity. Classic theme can cause crashes with the TimePicker.
The value configured in settings is ignored.
*/
this.setTheme(R.style.AppThemeCompat);
setContentView(R.layout.activity_manage_trigger_timeframe);
// if(Build.VERSION.SDK_INT == 34)
// Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.Android14TimePickerHint), ActivityManageTriggerTimeFrame.this).show();
startPicker = (TimePicker)findViewById(R.id.tpTimeFrameStart);
stopPicker = (TimePicker)findViewById(R.id.tpTimeFrameStop);
startPicker.setIs24HourView(true);
stopPicker.setIs24HourView(true);
stopPicker.setIs24HourView(true);
bSaveTimeFrame = (Button)findViewById(R.id.bSaveTimeFrame);
checkMonday = (CheckBox)findViewById(R.id.checkMonday);
@@ -15,7 +15,6 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@@ -54,6 +53,7 @@ public class ActivityManageTriggerWifi extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_manage_trigger_wifi);
rbTriggerWifiConnected = (RadioButton) findViewById(R.id.rbTriggerWifiConnected);
@@ -74,7 +74,7 @@ public class ActivityManageTriggerWifi extends Activity
if(
Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 29
&&
!ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
tvWifiTriggerNameLocationNotice.setVisibility(View.VISIBLE);
@@ -2,6 +2,7 @@ package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
@@ -11,6 +12,8 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
@@ -25,9 +28,9 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.jens.automation2.receivers.NotificationListener;
import androidx.core.content.ContextCompat;
import org.w3c.dom.DOMImplementationSource;
import com.jens.automation2.receivers.NotificationListener;
import java.util.ArrayList;
import java.util.Arrays;
@@ -66,6 +69,7 @@ public class ActivityPermissions extends Activity
public final static String permissionNameWireguard = "com.wireguard.android.permission.CONTROL_TUNNELS";
public final static String permissionNameGoogleActivityDetection = "com.google.android.gms.permission.ACTIVITY_RECOGNITION";
public final static String permissionNameSuperuser = "android.permission.ACCESS_SUPERUSER";
public final static String permissionNameProximity = "android.hardware.sensor.proximity";
public static ActivityPermissions getInstance()
{
@@ -84,6 +88,7 @@ public class ActivityPermissions extends Activity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.permissions_activity);
bCancelPermissions = (Button)findViewById(R.id.bCancelPermissions);
@@ -276,6 +281,19 @@ public class ActivityPermissions extends Activity
return false;
}
public static int getAmountOfRulesWhichLackPermissions(Context context)
{
int rulesWhichLackPermissions = 0;
for(Rule r : Rule.getRuleCollection())
{
if(!ActivityPermissions.havePermissionsForRule(r, context))
rulesWhichLackPermissions++;
}
return rulesWhichLackPermissions;
}
public static boolean havePermission(String s, Context context)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
@@ -314,9 +332,20 @@ public class ActivityPermissions extends Activity
{
return haveAccessibilityAccess(Miscellaneous.getAnyContext());
}
else if(s.equals(Manifest.permission.SCHEDULE_EXACT_ALARM) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
/*
It appears like as long as targetSdk has not been raised, this check
will return true even if the slider in the settings for that
permission is not enabled.
*/
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
return alarmManager.canScheduleExactAlarms();
}
else
{
int res = context.checkCallingOrSelfPermission(s);
// int res = context.checkCallingOrSelfPermission(s);
int res = ContextCompat.checkSelfPermission(context, s);
return (res == PackageManager.PERMISSION_GRANTED);
}
}
@@ -424,9 +453,20 @@ public class ActivityPermissions extends Activity
}
}
if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34 && !havePermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, workingContext))
{
addToArrayListUnique(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, requiredPermissions);
}
if(!havePermission(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, workingContext))
addToArrayListUnique(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, requiredPermissions);
if(Build.VERSION.SDK_INT >= 33 && BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
{
if (!havePermission(android.Manifest.permission.POST_NOTIFICATIONS, workingContext))
addToArrayListUnique(android.Manifest.permission.POST_NOTIFICATIONS, requiredPermissions);
}
if(!havePermission(Manifest.permission.READ_EXTERNAL_STORAGE, workingContext))
{
for (Profile p : Profile.getProfileCollection())
@@ -509,6 +549,8 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.BLUETOOTH_ADMIN, requiredPermissions);
addToArrayListUnique(Manifest.permission.BLUETOOTH, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
if(Build.VERSION.SDK_INT >= 31)
addToArrayListUnique(Manifest.permission.BLUETOOTH_CONNECT, requiredPermissions);
break;
case charging:
// addToArrayListUnique(Manifest.permission.READ_PHONE_STATE, requiredPermissions);
@@ -559,7 +601,10 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
break;
case timeFrame:
if(Build.VERSION.SDK_INT >= 31 && Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 31)
if(Build.VERSION.SDK_INT >= 31 && Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 31
||
Build.VERSION.SDK_INT >= 34 //https://developer.android.com/about/versions/14/changes/schedule-exact-alarms
)
addToArrayListUnique(Manifest.permission.SCHEDULE_EXACT_ALARM, requiredPermissions);
break;
case usb_host_connection:
@@ -573,7 +618,7 @@ public class ActivityPermissions extends Activity
(
Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 29
&&
isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
||
Build.VERSION.SDK_INT >= 33
@@ -588,6 +633,10 @@ public class ActivityPermissions extends Activity
if(Build.VERSION.SDK_INT >= 31 && Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 31)
addToArrayListUnique(Manifest.permission.SCHEDULE_EXACT_ALARM, requiredPermissions);
break;
// Proximity permission cannot be requested, but is always granted.
case proximity:
// addToArrayListUnique(ActivityPermissions.permissionNameProximity, requiredPermissions);
break;
default:
break;
}
@@ -605,12 +654,6 @@ public class ActivityPermissions extends Activity
if(targetProfile.changeIncomingCallsRingtone || targetProfile.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
break;
case disableScreenRotation:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
break;
case enableScreenRotation:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
break;
case playMusic:
break;
case controlMediaPlayback:
@@ -634,6 +677,8 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.BLUETOOTH, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
if(Build.VERSION.SDK_INT >= 31)
addToArrayListUnique(Manifest.permission.BLUETOOTH_CONNECT, requiredPermissions);
break;
case setDataConnection:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
@@ -697,7 +742,7 @@ public class ActivityPermissions extends Activity
// addToArrayListUnique("net.kollnig.missioncontrol.permission.ADMIN", requiredPermissions);
if(Build.VERSION.SDK_INT >= 29)
{
String parts[];
String[] parts;
if(action.getParameter2().contains(Action.actionParameter2Split))
parts = action.getParameter2().split(Action.actionParameter2Split);
else
@@ -705,7 +750,15 @@ public class ActivityPermissions extends Activity
// Permission only required for starts of activity, not broadcasts or services
if(parts[2].equals(ActivityManageActionStartActivity.startByActivityString))
if(
(
parts.length >= 4
&&
parts[3].equals(ActivityManageActionStartActivity.startByActivityString)
)
||
parts[2].equals(ActivityManageActionStartActivity.startByActivityString)
)
addToArrayListUnique(Manifest.permission.SYSTEM_ALERT_WINDOW, requiredPermissions);
}
break;
@@ -713,40 +766,12 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
getPermissionsForVariablesInUse(action.getParameter2(), requiredPermissions);
break;
case turnBluetoothOff:
addToArrayListUnique(Manifest.permission.BLUETOOTH_ADMIN, requiredPermissions);
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.BLUETOOTH, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case turnBluetoothOn:
addToArrayListUnique(Manifest.permission.BLUETOOTH_ADMIN, requiredPermissions);
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.BLUETOOTH, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case turnUsbTetheringOff:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
break;
case turnUsbTetheringOn:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
break;
case turnWifiOff:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case turnWifiOn:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case turnWifiTetheringOff:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case turnWifiTetheringOn:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
break;
case waitBeforeNextAction:
break;
case playSound:
@@ -772,7 +797,22 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.BIND_ACCESSIBILITY_SERVICE, requiredPermissions);
break;
case setLocationService:
addToArrayListUnique(Manifest.permission.WRITE_SECURE_SETTINGS, requiredPermissions);
case setSystemSetting:
String[] parts = action.getParameter2().split(Action.actionParameter2Split, -1);
if(parts.length < 4)
addToArrayListUnique(Manifest.permission.WRITE_SECURE_SETTINGS, requiredPermissions);
else
{
if(parts[0].equals(ActivityManageActionSetSystemSetting.targets[0]))
addToArrayListUnique(Manifest.permission.WRITE_SECURE_SETTINGS, requiredPermissions);
else if(parts[0].equals(ActivityManageActionSetSystemSetting.targets[1]))
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
else if(parts[0].equals(ActivityManageActionSetSystemSetting.targets[2]))
addToArrayListUnique(Manifest.permission.WRITE_SECURE_SETTINGS, requiredPermissions);
}
break;
case setScreenBrightness:
addToArrayListUnique(Manifest.permission.WRITE_SETTINGS, requiredPermissions);
break;
default:
break;
@@ -892,18 +932,6 @@ public class ActivityPermissions extends Activity
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.setWifiTethering))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOff))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOn))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnWifiOff))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnWifiOn))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnWifiTetheringOff))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnWifiTetheringOn))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.ACCESS_WIFI_STATE:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.pointOfInterest))
@@ -912,24 +940,12 @@ public class ActivityPermissions extends Activity
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.BLUETOOTH_ADMIN:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.bluetoothConnection))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.setBluetooth))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOff))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOn))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.BLUETOOTH:
case Manifest.permission.BLUETOOTH_CONNECT:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.bluetoothConnection))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.setBluetooth))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOff))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.turnBluetoothOn))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.GET_TASKS:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.process_started_stopped))
@@ -1036,11 +1052,18 @@ public class ActivityPermissions extends Activity
case Manifest.permission.WRITE_SECURE_SETTINGS:
for(String ruleName : getRulesUsing(Action.Action_Enum.setLocationService))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.setSystemSetting))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.READ_CALENDAR:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.calendarEvent))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
// Proximity permission cannot be requested, but is always granted.
// case ActivityPermissions.permissionNameProximity:
// for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.proximity))
// usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
// break;
}
return usingElements;
@@ -1058,7 +1081,7 @@ public class ActivityPermissions extends Activity
required permissions have been granted.
*/
super.onActivityResult(requestCode, resultCode, data);
// super.onActivityResult(requestCode, resultCode, data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
@@ -1121,16 +1144,16 @@ public class ActivityPermissions extends Activity
ArrayList<String> permissionList = new ArrayList<String>();
for(String permission : permissionNames)
{
if(permissionNames.equals(Manifest.permission.PROCESS_OUTGOING_CALLS))
if(permission.equals(Manifest.permission.PROCESS_OUTGOING_CALLS))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.PROCESS_OUTGOING_CALLS) && !Miscellaneous.isGooglePlayInstalled(Miscellaneous.getAnyContext()))
if(ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.PROCESS_OUTGOING_CALLS) && !Miscellaneous.isGooglePlayInstalled(Miscellaneous.getAnyContext()))
{
permissionList.add(permission);
}
}
else if(permissionNames.equals(Manifest.permission.SEND_SMS))
else if(permission.equals(Manifest.permission.SEND_SMS))
{
if(ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS) && !Miscellaneous.isGooglePlayInstalled(Miscellaneous.getAnyContext()))
if(ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS) && !Miscellaneous.isGooglePlayInstalled(Miscellaneous.getAnyContext()))
{
permissionList.add(permission);
}
@@ -1299,7 +1322,7 @@ public class ActivityPermissions extends Activity
{
if(requiredPermissions.contains(Manifest.permission.PROCESS_OUTGOING_CALLS))
{
if(!ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS)
if(!ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS)
&&
Miscellaneous.isGooglePlayInstalled(Miscellaneous.getAnyContext())
)
@@ -1310,7 +1333,7 @@ public class ActivityPermissions extends Activity
}
if(requiredPermissions.contains(Manifest.permission.SEND_SMS))
{
if(!ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS)
if(!ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), Manifest.permission.SEND_SMS)
)
{
requiredPermissions.remove(Manifest.permission.SEND_SMS);
@@ -1680,12 +1703,53 @@ public class ActivityPermissions extends Activity
mapActionPermissions.put("wakeupDevice", Manifest.permission.WAKE_LOCK);
}
public static boolean isPermissionDeclaratedInManifest(Context context, String permission)
public static boolean isServiceAvailable(Context context, String serviceName)
{
/*int flags = PackageManager.GET_ACTIVITIES
| PackageManager.GET_CONFIGURATIONS
| PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_GIDS | PackageManager.GET_INSTRUMENTATION
| PackageManager.GET_INTENT_FILTERS
| PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
| PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
| PackageManager.GET_SIGNATURES;
PackageManager packageManager = getPackageManager();
List<PackageInfo> installedPackages = packageManager.getInstalledPackages(flags);
for (PackageInfo packageInfo : installedPackages)
{
ServiceInfo[] services = packageInfo.services;
PermissionInfo[] permissions = packageInfo.permissions;
}*/
StringBuffer buffer = new StringBuffer();
try
{
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo("com.jens.automation2", PackageManager.GET_SERVICES);
ServiceInfo[] services = packageInfo.services;
for (ServiceInfo serviceInfo : services)
{
if(serviceInfo.name.endsWith(serviceName))
return true;
}
PermissionInfo[] permissions = packageInfo.permissions;
}
catch (PackageManager.NameNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static boolean isPermissionDeclaredInManifest(Context context, String permission)
{
PackageManager pm = context.getPackageManager();
try
{
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] requestedPermissions = null;
if (packageInfo != null)
{
@@ -17,6 +17,13 @@ public class ActivitySettings extends PreferenceActivity
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
// Dark Theme doesn't work in PreferenceActivity, so only a bright theme is readable
if(Settings.uiTheme != 0)
this.setTheme(R.style.AppThemeCompatLight);
// Miscellaneous.setUiTheme(this);
addPreferencesFromResource(layout.activity_settings);
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_apk))
@@ -31,6 +31,7 @@ public class ActivityVolumeTest extends Activity
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
Miscellaneous.setUiTheme(this);
setContentView(R.layout.activity_volume_calibration);
tvCurrentVolume = (TextView)findViewById(R.id.tvCurrentVolume);
@@ -49,20 +50,15 @@ public class ActivityVolumeTest extends Activity
@Override
public void onStopTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser)
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
etReferenceValue.setText(String.valueOf(sbReferenceValue.getProgress()));
}
@@ -22,7 +22,7 @@ public class AsyncTasks
try
{
String result = Miscellaneous.downloadURL("https://server47.de/automation/?action=getLatestVersionCode", null, null, ActivityManageActionTriggerUrl.methodGet).trim();
String result = Miscellaneous.downloadURL("https://server47.de/automation/?action=getLatestVersionCode", null, null, ActivityManageActionTriggerUrl.methodGet, null).trim();
int latestVersion = Integer.parseInt(result);
// At this point the update check itself has already been successful.
@@ -1,5 +1,7 @@
package com.jens.automation2;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -12,6 +14,7 @@ import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
@@ -28,6 +31,7 @@ import androidx.core.app.NotificationManagerCompat;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider;
import com.jens.automation2.receivers.CalendarReceiver;
import com.jens.automation2.receivers.DateTimeListener;
import com.jens.automation2.receivers.PackageReplacedReceiver;
import com.jens.automation2.receivers.PhoneStatusListener;
@@ -127,7 +131,18 @@ public class AutomationService extends Service implements OnInitListener
// Store a reference to myself. Other classes often need a context or something, this can provide that.
centralInstance = this;
Miscellaneous.setDisplayLanguage(AutomationService.this);
/*
This has been reported to throw a NullPointerException under
rare circumstances. The root cause remains unknown.
*/
try
{
Miscellaneous.setDisplayLanguage(AutomationService.this);
}
catch(NullPointerException e)
{
Miscellaneous.logEvent("e", "setDisplayLanguage()", Log.getStackTraceString(e), 3);
}
}
public boolean checkStartupRequirements(Context context, boolean startAtBoot)
@@ -144,6 +159,15 @@ public class AutomationService extends Service implements OnInitListener
ActivityPermissions.requestSpecificPermission(Manifest.permission.FOREGROUND_SERVICE);
return false;
}
else
{
if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34 && !ActivityPermissions.havePermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, context))
{
Toast.makeText(context, context.getResources().getString(R.string.permissionForegroundServiceTypeSpecialUseRequired), Toast.LENGTH_LONG).show();
Miscellaneous.logEvent("e", "Permission", "Don't have permission FOREGROUND_SERVICE_SPECIAL_USE. Will request it now.", 4);
return false;
}
}
}
if (
@@ -156,6 +180,17 @@ public class AutomationService extends Service implements OnInitListener
Rule.getRuleCollection().size() == 0
)
{
if(
Rule.getRuleCollection().size() > 0
&&
Rule.getRuleCollection().size() == ActivityPermissions.getAmountOfRulesWhichLackPermissions(Miscellaneous.getAnyContext())
)
{
Miscellaneous.logEvent("w", "AutomationService", "Don't have complete permissions for any defined rule. Not starting service.", 1);
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStartPermissions), Toast.LENGTH_LONG).show();
return false;
}
if (startAtBoot)
{
/*
@@ -231,7 +266,7 @@ public class AutomationService extends Service implements OnInitListener
updateNotification();
if (isMainActivityRunning(this))
if(isMainActivityRunning(this))
ActivityMainScreen.updateMainScreen();
this.isRunning = true;
@@ -308,7 +343,10 @@ public class AutomationService extends Service implements OnInitListener
ReceiverCoordinator.applySettingsAndRules();
DateTimeListener.reloadAlarms();
DateTimeListener.setOrResetAlarms();
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaredInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
CalendarReceiver.armOrRearmTimer();
}
@Override
@@ -377,6 +415,20 @@ public class AutomationService extends Service implements OnInitListener
r.activate(AutomationService.this, false);
}
if(!Settings.hasBeenDone(Settings.constVersion143StartOtherProgramConfigEditHint))
{
if(Rule.isAnyRuleUsing(Action.Action_Enum.startOtherActivity))
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissibleNotificationWithDelay(1010, null, getResources().getString(R.string.version143StartOtherActivityHint), 9123, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, null);
else
Miscellaneous.createDismissibleNotification(null, getResources().getString(R.string.version143StartOtherActivityHint), 9123, false, AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE, null);
}
Settings.considerDone(Settings.constVersion143StartOtherProgramConfigEditHint);
Settings.writeSettings(Miscellaneous.getAnyContext());
}
Settings.serviceStartDone = true;
Settings.deviceStartDone = true;
}
@@ -463,7 +515,12 @@ public class AutomationService extends Service implements OnInitListener
if(Miscellaneous.googleToBlameForLocation(true))
{
Intent intent = new Intent(AutomationService.this, ActivityMainTabLayout.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
PendingIntent pi;
// if(Miscellaneous.getTargetSDK(AutomationService.this) >= Build.VERSION_CODES.S)
pi = PendingIntent.getActivity(AutomationService.this, 0, intent, FLAG_IMMUTABLE);
// else
// pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
Miscellaneous.logEvent("w", "Features disabled", "Background location disabled because Google to blame.", 5);
@@ -480,6 +537,7 @@ public class AutomationService extends Service implements OnInitListener
{
Intent myServiceIntent = new Intent(context, AutomationService.class);
myServiceIntent.putExtra("startAtBoot", startAtBoot);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
context.startForegroundService(myServiceIntent);
else
@@ -514,42 +572,6 @@ public class AutomationService extends Service implements OnInitListener
centralInstance = null;
Settings.serviceStartDone = false;
}
protected static Builder createDefaultNotificationBuilderOld()
{
Builder builder = new Builder(AutomationService.getInstance());
builder.setContentTitle("Automation");
if(Settings.showIconWhenServiceIsRunning)
{
if(BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))
builder.setSmallIcon(R.drawable.crane);
else
builder.setSmallIcon(R.drawable.ic_launcher);
}
builder.setCategory(Notification.CATEGORY_SERVICE);
builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(myPendingIntent);
Notification defaultNotification = builder.build();
defaultNotification.icon = R.drawable.crane;
defaultNotification.when = System.currentTimeMillis();
// defaultNotification.defaults |= Notification.DEFAULT_VIBRATE;
// defaultNotification.defaults |= Notification.DEFAULT_LIGHTS;
defaultNotification.flags |= Notification.FLAG_AUTO_CANCEL;
// defaultNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
defaultNotification.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
// defaultNotification.ledARGB = Color.YELLOW;
// defaultNotification.ledOnMS = 1500;
// defaultNotification.ledOffMS = 1500;
return builder;
}
protected static NotificationCompat.Builder createServiceNotificationBuilder()
{
@@ -599,6 +621,9 @@ public class AutomationService extends Service implements OnInitListener
@SuppressWarnings("deprecation")
public static void updateNotification()
{
if(!Settings.showIconWhenServiceIsRunning && Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return;
AutomationService instance = getInstance();
if(instance != null)
@@ -647,7 +672,11 @@ public class AutomationService extends Service implements OnInitListener
lastRuleString = instance.getResources().getString(R.string.lastRule) + " n./a.";
}
String textToDisplay = bodyText + " " + lastRuleString;
String textToDisplay;
if(bodyText.length() > 0)
textToDisplay = bodyText + " " + lastRuleString;
else
textToDisplay = lastRuleString;
if(notificationBuilder == null)
notificationBuilder = createServiceNotificationBuilder();
@@ -664,7 +693,10 @@ public class AutomationService extends Service implements OnInitListener
myNotification.flags |= Notification.FLAG_NO_CLEAR;
// notificationManager.notify(notificationId, myNotification);
instance.startForeground(notificationId, myNotification);
// if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34)
// instance.startForeground(notificationId, myNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
// else
instance.startForeground(notificationId, myNotification);
}
}
@@ -679,8 +711,6 @@ public class AutomationService extends Service implements OnInitListener
@Override
public void onInit(int status)
{
// TODO Auto-generated method stub
}
/**
@@ -37,20 +37,22 @@ import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.location.LocationProvider;
import com.jens.automation2.receivers.CalendarReceiver;
import com.jens.automation2.receivers.NotificationListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
@@ -73,6 +75,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.Thread.UncaughtExceptionHandler;
@@ -89,6 +92,7 @@ import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
@@ -98,6 +102,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -117,14 +122,42 @@ import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.documentfile.provider.DocumentFile;
import eu.chainfire.libsuperuser.Shell;
public class Miscellaneous extends Service
{
protected static String writeableFolderStringCache = null;
protected final static String http_error_string = "HTTP_ERROR";
protected final static String last_trigger_url_result_string = "last_trigger_url_result";
protected final static String httpMainData = "httpMainData";
protected final static String doNoEncodingString = "NoEncoding";
protected final static String httpEncoding = "UTF-8";
public static Context startupContext;
public static final String lineSeparator = System.getProperty("line.separator");
public static String downloadURL(String url, String username, String password, String method)
public static class TrustAllCertificates implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
// Do nothing (trust all clients)
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
// Do nothing (trust all servers)
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0]; // No accepted issuers
}
}
public static String downloadURL(String url, String username, String password, String method, Map<String, String> httpParams)
{
HttpClient httpclient = new DefaultHttpClient();
StringBuilder responseBody = new StringBuilder();
@@ -138,12 +171,24 @@ public class Miscellaneous extends Service
HttpURLConnection connection;
if(url.toLowerCase().contains("https"))
{
connection = (HttpsURLConnection) urlObject.openConnection();
}
{
connection = (HttpsURLConnection) urlObject.openConnection();
if(Settings.httpAcceptAllCertificates)
{
SSLContext sslContext = SSLContext.getInstance("TLS"); // Use "TLS" (not "SSL" which is outdated)
sslContext.init(
null, // No KeyManager (client authentication not needed)
new TrustManager[]{new TrustAllCertificates()}, // Use our trust manager
new SecureRandom() // Secure random number generator
);
((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory());
((HttpsURLConnection)connection).setHostnameVerifier((hostname, session) -> true); // Trust all hostnames
}
}
else
connection = (HttpURLConnection) urlObject.openConnection();
// Add http simple authentication if specified
if(username != null && password != null)
{
@@ -154,7 +199,26 @@ public class Miscellaneous extends Service
}
else if(method.equals(ActivityManageActionTriggerUrl.methodPost))
connection.setRequestMethod("POST");
if(httpParams.size() > 0)
{
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setDoInput(true);
connection.setDoOutput(true);
List<NameValuePair> paramPairs = new ArrayList<NameValuePair>();
for(String key : httpParams.keySet())
paramPairs.add(new BasicNameValuePair(key, httpParams.get(key)));
OutputStream os = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, httpEncoding));
writer.write(getQuery(paramPairs, method));
writer.flush();
writer.close();
}
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in = new BufferedReader (new InputStreamReader (content));
String line;
@@ -174,13 +238,64 @@ public class Miscellaneous extends Service
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
if(errorFound)
return "httpError";
return http_error_string;
else
return responseBody.toString();
}
}
private static String getQuery(List<NameValuePair> params, String method) throws UnsupportedEncodingException
{
StringBuilder result = new StringBuilder();
boolean first = true;
for (NameValuePair pair : params)
{
if (method.equals(ActivityManageActionTriggerUrl.methodGet))
{
if (first)
first = false;
else
result.append("&");
}
else if (pair.getName().startsWith(httpMainData))
continue; // if post and main data skip lookup run
result.append(pair.getName());
result.append("=");
if (pair.getName().endsWith(doNoEncodingString))
result.append(URLEncoder.encode(pair.getValue(), httpEncoding));
else
result.append(pair.getValue());
}
/*
If method is POST and there's a httpMainData field, we transfer
this one at the end without parameter name and equals sign.
*/
if (method.equals(ActivityManageActionTriggerUrl.methodPost))
{
for (NameValuePair pair : params)
{
if (pair.getName().startsWith(httpMainData))
{
if (pair.getName().endsWith(doNoEncodingString))
result.append(pair.getValue());
else
result.append(URLEncoder.encode(pair.getValue(), httpEncoding));
return result.toString();
}
}
}
return result.toString();
}
public static String downloadURLwithoutCertificateChecking(String url, String username, String password, String method)
public static String downloadUrlWithoutCertificateChecking(String url, String username, String password, String method, Map<String, String> httpParams)
{
try
{
@@ -195,18 +310,12 @@ public class Miscellaneous extends Service
method.equals(ActivityManageActionTriggerUrl.methodPost)
||
(username != null && password != null)
||
httpParams.size() > 0
)
httpRequest = new HttpPost(url);
else
httpRequest = new HttpGet(url);
/*httpRequest = new HttpEntityEnclosingRequestBase()
{
@Override
public String getMethod()
{
return "GET";
}
};*/
// Add http simple authentication if specified
if(username != null && password != null)
@@ -214,6 +323,16 @@ public class Miscellaneous extends Service
String encodedCredentials = Base64.encodeToString(new String(username + ":" + password).getBytes(), Base64.DEFAULT);
httpRequest.addHeader("Authorization", "Basic " + encodedCredentials);
}
if(httpParams.size() > 0)
{
List<NameValuePair> paramPairs = new ArrayList<NameValuePair>();
for(String key : httpParams.keySet())
paramPairs.add(new BasicNameValuePair(key, httpParams.get(key)));
((HttpPost)httpRequest).setEntity(new UrlEncodedFormEntity(paramPairs, "UTF-8"));
}
HttpResponse response = httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
@@ -225,8 +344,8 @@ public class Miscellaneous extends Service
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "HTTP error", Log.getStackTraceString(e), 3);
return "httpError";
Miscellaneous.logEvent("e", "HTTP error", Log.getStackTraceString(e), 3);
return http_error_string;
}
// finally
// {
@@ -251,25 +370,9 @@ public class Miscellaneous extends Service
@Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
// public static void logEvent(String type, String header, String description)
// {
// if(type.equals("e"))
// Log.e(header, description);
//
// if(type.equals("w"))
// Log.w(header, description);
//
// if(type.equals("i"))
// Log.i(header, description);
//
// if(Settings.writeLogFile)
// writeToLogFile(type, header, description);
// }
public static void logEvent(String type, String header, String description, int logLevel)
{
try
@@ -281,15 +384,18 @@ public class Miscellaneous extends Service
header = "Automation";
}
if(type.equals("e"))
Log.e(header, description);
if(Settings.logToConsole)
{
if (type.equals("e"))
Log.e(header, description);
if (type.equals("w"))
Log.w(header, description);
if (type.equals("i"))
Log.i(header, description);
}
if(type.equals("w"))
Log.w(header, description);
if(type.equals("i"))
Log.i(header, description);
if(Settings.writeLogFile && Settings.logLevel >= logLevel)
{
writeToLogFile(type, header, description);
@@ -306,7 +412,6 @@ public class Miscellaneous extends Service
{
logCleanerRunning = true;
long maxSizeInBytes = (long)Settings.logFileMaxSize * 1024 * 1024;
if(logFile.exists() && logFile.length() > (maxSizeInBytes))
@@ -554,7 +659,45 @@ public class Miscellaneous extends Service
Miscellaneous.logEvent("i", "TimeCompare", "Default return code. Shouldn't be here.", 5);
return 0;
}
public static int compareTimes(Calendar calOne, Calendar calTwo)
{
if(calOne.get(Calendar.HOUR_OF_DAY) == calTwo.get(Calendar.HOUR_OF_DAY) && calOne.get(Calendar.MINUTE) == calTwo.get((Calendar.MINUTE)))
{
// Miscellaneous.logEvent("i", "TimeCompare", "Times are equal.");
return 0;
}
if(calOne.get(Calendar.HOUR_OF_DAY) > calTwo.get(Calendar.HOUR_OF_DAY))
{
// Miscellaneous.logEvent("i", "TimeCompare", "Time1 is bigger/later by hours.");
return -1;
}
if(calOne.get(Calendar.HOUR_OF_DAY) < calTwo.get(Calendar.HOUR_OF_DAY))
{
// Miscellaneous.logEvent("i", "TimeCompare", "Time2 is bigger/later by hours.");
return 1;
}
if(calOne.get(Calendar.HOUR_OF_DAY) == calTwo.get(Calendar.HOUR_OF_DAY))
{
if(calOne.get(Calendar.MINUTE) < calTwo.get(Calendar.MINUTE))
{
// Miscellaneous.logEvent("i", "TimeCompare", "Hours are equal. Time2 is bigger/later by minutes.");
return 1;
}
if(calOne.get(Calendar.MINUTE) > calTwo.get(Calendar.MINUTE))
{
// Miscellaneous.logEvent("i", "TimeCompare", "Hours are equal. Time1 is bigger/later by minutes.");
return -1;
}
}
Miscellaneous.logEvent("i", "TimeCompare", "Default return code. Shouldn't be here.", 5);
return 0;
}
public static String convertStreamToString(InputStream is)
@@ -648,7 +791,9 @@ public class Miscellaneous extends Service
source.contains("[H]") ||
source.contains("[i]") ||
source.contains("[s]") ||
source.contains("[ms]")
source.contains("[ms]") ||
source.contains("[w]") ||
source.contains("[F]")
)
{
Calendar cal = Calendar.getInstance();
@@ -716,6 +861,24 @@ public class Miscellaneous extends Service
{
source = source.replace("[ms]", String.valueOf(cal.get(Calendar.MILLISECOND)));
}
if(source.contains("[w]"))
{
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
Date d = new Date();
String dayOfTheWeek = sdf.format(d);
// source = source.replace("[w]", LocalDate.now().getDayOfWeek().name());
source = source.replace("[w]", dayOfTheWeek);
}
if(source.contains("[F]"))
{
SimpleDateFormat sdf = new SimpleDateFormat("MMMM");
Date d = new Date();
String month = sdf.format(d);
// source = source.replace("[F]", LocalDate.now().getMonth().name());
source = source.replace("[F]", month);
}
}
if(source.contains("[notificationTitle]"))
@@ -725,7 +888,7 @@ public class Miscellaneous extends Service
String notificationTitle = NotificationListener.getLastNotification().getTitle();
if (notificationTitle != null && notificationTitle.length() > 0)
source = source.replace("[notificationTitle]", escapeStringForUrl(notificationTitle));
source = source.replace("[notificationTitle]", notificationTitle);
else
{
source = source.replace("[notificationTitle]", "notificationTitle unknown");
@@ -746,7 +909,8 @@ public class Miscellaneous extends Service
String notificationText = NotificationListener.getLastNotification().getText();
if (notificationText != null && notificationText.length() > 0)
source = source.replace("[notificationText]", escapeStringForUrl(notificationText));
//source = source.replace("[notificationText]", escapeStringForUrl(notificationText));
source = source.replace("[notificationText]", notificationText);
else
{
source = source.replace("[notificationText]", "notificationText unknown");
@@ -760,6 +924,78 @@ public class Miscellaneous extends Service
}
}
if(source.contains("[" + last_trigger_url_result_string + "]"))
{
try
{
source = source.replace("[" + last_trigger_url_result_string + "]", AutomationService.getInstance().getVariableMap().get(last_trigger_url_result_string));
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable " + last_trigger_url_result_string + ".", 3);
}
}
if(source.contains("[last_run_executable_exit_code]"))
{
try
{
source = source.replace("[last_run_executable_exit_code]", AutomationService.getInstance().getVariableMap().get("last_run_executable_exit_code"));
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable last_run_executable_exit_code.", 3);
}
}
if(source.contains("[last_run_executable_output]"))
{
try
{
source = source.replace("[last_run_executable_output]", AutomationService.getInstance().getVariableMap().get("last_run_executable_output"));
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable last_run_executable_output.", 3);
}
}
if(source.contains("[last_calendar_title]"))
{
try
{
source = source.replace("[last_calendar_title]", CalendarReceiver.getLastTriggeringEvent().title);
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable last_calendar_title.", 3);
}
}
if(source.contains("[last_calendar_description]"))
{
try
{
source = source.replace("[last_calendar_description]", CalendarReceiver.getLastTriggeringEvent().description);
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable last_calendar_description.", 3);
}
}
if(source.contains("[last_calendar_location]"))
{
try
{
source = source.replace("[last_calendar_location]", CalendarReceiver.getLastTriggeringEvent().location);
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "Variable replacement", "Error replacing variable last_calendar_location.", 3);
}
}
while(source.contains("[variable-"))
{
int pos1 = source.indexOf("[variable-");
@@ -842,36 +1078,40 @@ public class Miscellaneous extends Service
*/
public static boolean isPhoneRooted()
{
// if(true)
// return true;
// get from build info
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys"))
{
return true;
}
// check if /system/app/Superuser.apk is present
try
{
File file = new File("/system/app/Superuser.apk");
if (file.exists())
return Shell.SU.available();
}
catch(Exception e)
{
// get from build info
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys"))
{
return true;
}
}
catch (Exception e1)
{
// ignore
}
// try executing commands
return canExecuteCommand("/system/xbin/which su")
||
canExecuteCommand("/system/bin/which su")
||
canExecuteCommand("which su");
// check if /system/app/Superuser.apk is present
try
{
File file = new File("/system/app/Superuser.apk");
if (file.exists())
{
return true;
}
}
catch (Exception e1)
{
// ignore
}
// try executing commands
return canExecuteCommand("/system/xbin/which su")
||
canExecuteCommand("/system/bin/which su")
||
canExecuteCommand("which su");
}
}
// executes a command on the system
@@ -919,51 +1159,45 @@ public class Miscellaneous extends Service
private static void disableSSLCertificateChecking()
{
try
{
SSLSocketFactory ssf = null;
try
{
SSLContext ctx = SSLContext.getInstance("TLS");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
ssf = new MySSLSocketFactoryInsecure(trustStore);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ctx.init(null, null, null);
{
SSLSocketFactory ssf = null;
try
{
SSLContext ctx = SSLContext.getInstance("TLS");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
ssf = new MySSLSocketFactoryInsecure(trustStore);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ctx.init(null, null, null);
// return new DefaultHttpClient(ccm, client.getParams());
}
catch (Exception ex)
{
ex.printStackTrace();
}
catch (Exception ex)
{
ex.printStackTrace();
// return null;
}
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, getInsecureTrustManager(), new java.security.SecureRandom());
}
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, getInsecureTrustManager(), new java.security.SecureRandom());
// HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// HttpsURLConnection.setDefaultSSLSocketFactory(ssf);
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(getInsecureHostnameVerifier());
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
catch (KeyManagementException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(getInsecureHostnameVerifier());
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
catch (KeyManagementException e)
{
Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4);
}
catch (NoSuchAlgorithmException e)
{
Miscellaneous.logEvent("e", "SSL", Log.getStackTraceString(e), 4);
}
}
public static TrustManager[] getInsecureTrustManager()
@@ -1180,7 +1414,8 @@ public class Miscellaneous extends Service
builder.setOnlyAlertOnce(true);
if(Settings.showIconWhenServiceIsRunning && notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
//if(Settings.showIconWhenServiceIsRunning && notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
if(notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
{
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
builder.setSmallIcon(R.drawable.crane);
@@ -1913,6 +2148,50 @@ public class Miscellaneous extends Service
return formattedDate;
}
public static int arraySearchIndexOf(String[] haystack, String needle, boolean caseSensitive, boolean matchFullLine)
{
if(matchFullLine)
{
if(caseSensitive)
{
for (int i = 0; i < haystack.length; i++)
{
if (haystack[i].equals(needle))
return i;
}
}
else
{
for (int i = 0; i < haystack.length; i++)
{
if (haystack[i].toLowerCase().equals(needle.toLowerCase()))
return i;
}
}
}
else
{
if(caseSensitive)
{
for (int i = 0; i < haystack.length; i++)
{
if (haystack[i].contains(needle))
return i;
}
}
else
{
for (int i = 0; i < haystack.length; i++)
{
if (haystack[i].toLowerCase().contains(needle.toLowerCase()))
return i;
}
}
}
return -1;
}
public static boolean arraySearch(String[] haystack, String needle, boolean caseSensitive, boolean matchFullLine)
{
if(matchFullLine)
@@ -2032,6 +2311,22 @@ public class Miscellaneous extends Service
return context.getApplicationContext().getApplicationInfo().targetSdkVersion;
}
public static void setUiTheme(Context context)
{
switch(Settings.uiTheme)
{
case 0:
context.setTheme(R.style.AppTheme);
break;
case 1:
context.setTheme(R.style.AppThemeCompat);
break;
default:
context.setTheme(R.style.AppTheme);
break;
}
}
public static void setDisplayLanguage(Context context)
{
if(!Settings.displayLanguage.equals(Settings.default_displayLanguage))
@@ -2080,4 +2375,10 @@ public class Miscellaneous extends Service
return output;
}
public static String getCallingMethodName()
{
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
}
@@ -79,7 +79,7 @@ public class News
if (!(new File(filePath)).exists() || Settings.lastNewsPolltime == Settings.default_lastNewsPolltime || now.getTimeInMillis() >= Settings.lastNewsPolltime + (long)(Settings.newsDisplayForXDays * 24 * 60 * 60 * 1000))
{
String newsUrl = "https://server47.de/automation/appNews.php";
newsContent = Miscellaneous.downloadURL(newsUrl, null, null, ActivityManageActionTriggerUrl.methodGet);
newsContent = Miscellaneous.downloadURL(newsUrl, null, null, ActivityManageActionTriggerUrl.methodGet, null);
// Cache content to local storage
if(Miscellaneous.writeStringToFile(filePath, newsContent))
@@ -694,22 +694,16 @@ public class PointOfInterest implements Comparable<PointOfInterest>
@Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
}
}
@@ -38,6 +38,9 @@ public class Profile implements Comparable<Profile>
protected boolean changeVolumeNotifications;
protected int volumeNotifications;
protected boolean changeVolumeRingtones;
protected int volumeRingtones;
protected boolean changeVolumeAlarms;
protected int volumeAlarms;
@@ -145,6 +148,26 @@ public class Profile implements Comparable<Profile>
return volumeNotifications;
}
public boolean getChangeVolumeRingtones()
{
return changeVolumeRingtones;
}
public void setChangeVolumeRingtones(boolean changeVolumeRingtones)
{
this.changeVolumeRingtones = changeVolumeRingtones;
}
public int getVolumeRingtones()
{
return volumeRingtones;
}
public void setVolumeRingtones(int volumeRingtones)
{
this.volumeRingtones = volumeRingtones;
}
public void setChangeVolumeAlarms(boolean changeVolumeAlarms)
{
this.changeVolumeAlarms = changeVolumeAlarms;
@@ -520,52 +543,92 @@ public class Profile implements Comparable<Profile>
{
AudioManager am = (AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE);
if(changeSoundMode)
Actions.setSound(context, soundMode);
if(changeSoundMode)
{
Miscellaneous.logEvent("i", "Profile", "Setting sound mode to " + String.valueOf(soundMode), 4);
Actions.setSound(context, soundMode);
}
if(changeDndMode)
Actions.setDoNotDisturb(context, dndMode);
{
Miscellaneous.logEvent("i", "Profile", "Setting DND mode to " + String.valueOf(dndMode), 4);
Actions.setDoNotDisturb(context, dndMode);
}
if(changeVolumeMusicVideoGameMedia)
am.setStreamVolume(AudioManager.STREAM_MUSIC, volumeMusic, AudioManager.FLAG_PLAY_SOUND);
{
Miscellaneous.logEvent("i", "Profile", "Setting media volume to " + String.valueOf(volumeMusic), 4);
am.setStreamVolume(AudioManager.STREAM_MUSIC, volumeMusic, AudioManager.FLAG_PLAY_SOUND);
}
if(changeVolumeNotifications)
am.setStreamVolume(AudioManager.STREAM_NOTIFICATION, volumeNotifications, AudioManager.FLAG_PLAY_SOUND);
{
Miscellaneous.logEvent("i", "Profile", "Setting notification volume to " + String.valueOf(volumeNotifications), 4);
am.setStreamVolume(AudioManager.STREAM_NOTIFICATION, volumeNotifications, AudioManager.FLAG_PLAY_SOUND);
}
if(Build.VERSION.SDK_INT >= 34)
{
if (changeVolumeRingtones)
{
Miscellaneous.logEvent("i", "Profile", "Setting ring volume to " + String.valueOf(volumeRingtones), 4);
am.setStreamVolume(AudioManager.STREAM_RING, volumeRingtones, AudioManager.FLAG_PLAY_SOUND);
}
}
if(changeVolumeAlarms)
am.setStreamVolume(AudioManager.STREAM_ALARM, volumeAlarms, AudioManager.FLAG_PLAY_SOUND);
{
Miscellaneous.logEvent("i", "Profile", "Setting alarm volume to " + String.valueOf(volumeAlarms), 4);
am.setStreamVolume(AudioManager.STREAM_ALARM, volumeAlarms, AudioManager.FLAG_PLAY_SOUND);
}
if(changeIncomingCallsRingtone)
if(incomingCallsRingtone != null)
applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
{
if (incomingCallsRingtone != null)
{
Miscellaneous.logEvent("i", "Profile", "Setting ringtone " + incomingCallsRingtone, 4);
applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
}
}
if(changeVibrateWhenRinging)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
Miscellaneous.logEvent("i", "Profile", "Setting vibrate when ringing to " + String.valueOf(vibrateWhenRinging?1:0), 4);
android.provider.Settings.System.putInt(context.getContentResolver(), "vibrate_when_ringing", vibrateWhenRinging?1:0);
}
else
{
Miscellaneous.logEvent("i", "Profile", "Setting vibrate when ringing to " + String.valueOf(vibrateWhenRinging), 4);
if (vibrateWhenRinging)
am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ON);
am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ON);
else
am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
}
}
if(changeNotificationRingtone)
if(notificationRingtone != null)
applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
{
if (notificationRingtone != null)
{
Miscellaneous.logEvent("i", "Profile", "Setting notification ringtone to " + String.valueOf(notificationRingtone), 4);
applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
}
}
if(changeScreenLockUnlockSound)
{
Miscellaneous.logEvent("i", "Profile", "Setting lockscreen sounds enabled to " + String.valueOf(screenLockUnlockSound ? 1 : 0), 4);
android.provider.Settings.System.putInt(context.getContentResolver(), "lockscreen_sounds_enabled" , screenLockUnlockSound ? 1 : 0);
}
if(changeAudibleSelection)
{
if(audibleSelection)
Miscellaneous.logEvent("i", "Profile", "Setting audible selection to " + String.valueOf(audibleSelection ? 1 : 0), 4);
if(audibleSelection)
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SOUND_EFFECTS_ENABLED, 1); // enable
else
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SOUND_EFFECTS_ENABLED, 0); // dissable
@@ -573,7 +636,9 @@ public class Profile implements Comparable<Profile>
if(changeHapticFeedback)
{
if(hapticFeedback)
Miscellaneous.logEvent("i", "Profile", "Setting haptic feedback to " + String.valueOf(hapticFeedback ? 1 : 0), 4);
if(hapticFeedback)
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED, 1); // enable
else
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED, 0); // disable
@@ -585,7 +650,8 @@ public class Profile implements Comparable<Profile>
}
finally
{
Miscellaneous.logEvent("i", "Profile", "Checking for applicable rules after profile " + this.getName() + " has been activated.", 2);
Miscellaneous.logEvent("i", "Profile", "Profile activation complete: " + this.getName(), 3);
Miscellaneous.logEvent("i", "Profile", "Checking for applicable rules after profile " + this.getName() + " has been activated.", 3);
List<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.profileActive);
for(int i=0; i<ruleCandidates.size(); i++)
{
@@ -637,6 +703,15 @@ public class Profile implements Comparable<Profile>
return false;
}
if(Build.VERSION.SDK_INT >= 34)
{
if (changeVolumeRingtones)
{
if (am.getStreamVolume(AudioManager.STREAM_RING) != volumeRingtones)
return false;
}
}
if (changeVolumeAlarms)
{
if (am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
@@ -1,5 +1,6 @@
package com.jens.automation2;
import android.Manifest;
import android.os.Build;
import android.util.Log;
@@ -18,6 +19,7 @@ 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.ProximityReceiver;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.SubSystemStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
@@ -212,8 +214,11 @@ public class ReceiverCoordinator
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaredInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
CalendarReceiver.startCalendarReceiver(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.proximity))
ProximityReceiver.startProximityReceiver(AutomationService.getInstance());
}
public static void stopAllReceivers()
@@ -233,6 +238,7 @@ public class ReceiverCoordinator
DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance());
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
SubSystemStateReceiver.getInstance().stopListener(AutomationService.getInstance());
ProximityReceiver.stopProximityReceiver();
try
{
@@ -469,6 +475,19 @@ public class ReceiverCoordinator
}
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaredInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
{
if(!CalendarReceiver.getInstance().isListenerRunning())
CalendarReceiver.getInstance().startListener(AutomationService.getInstance());
else
CalendarReceiver.armOrRearmTimer();
}
else
{
if(CalendarReceiver.getInstance().isListenerRunning())
CalendarReceiver.getInstance().stopListener(AutomationService.getInstance());
}
AutomationService.updateNotification();
}
}
@@ -19,8 +19,9 @@ public class Settings implements SharedPreferences
public static final String folderName = "Automation";
public static final String zipFileName = "automation.zip";
public static final String constNewsOptInDone ="newsOptInDone";
public static final String constNotificationChannelCleanupApk118 ="notificationChannelCleanupApk118";
public static final String constNewsOptInDone = "newsOptInDone";
public static final String constNotificationChannelCleanupApk118 = "notificationChannelCleanupApk118";
public static final String constVersion143StartOtherProgramConfigEditHint = "constVersion143StartOtherProgramConfigEditHint";
public static long minimumDistanceChangeForGpsUpdate;
public static long minimumDistanceChangeForNetworkUpdate;
@@ -29,6 +30,7 @@ public class Settings implements SharedPreferences
public static int gpsTimeout;
public static long minimumTimeBetweenUpdate;
public static boolean startServiceAtSystemBoot;
public static boolean logToConsole;
public static boolean writeLogFile;
public static long logLevel;
public static int logFileMaxSize;
@@ -61,6 +63,7 @@ public class Settings implements SharedPreferences
public static int activityDetectionFrequency;
public static int activityDetectionRequiredProbability;
public static boolean privacyLocationing;
public static int uiTheme;
public static int startScreen;
public static int tabsPlacement;
public static boolean executeRulesAndProfilesWithSingleClick;
@@ -97,6 +100,7 @@ public class Settings implements SharedPreferences
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_logToConsole = false;
public static final boolean default_writeLogFile = false;
public static final long default_logLevel = 2;
public static final int default_logFileMaxSize = 10;
@@ -128,6 +132,7 @@ public class Settings implements SharedPreferences
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_uiTheme = 0;
public static final int default_startScreen = 0;
public static final int default_tabsPlacement = 0;
public static final boolean default_executeRulesAndProfilesWithSingleClick = false;
@@ -149,56 +154,45 @@ public class Settings implements SharedPreferences
@Override
public Editor edit()
{
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, ?> getAll()
{
// TODO Auto-generated method stub
return null;
}
@Override
public boolean getBoolean(String arg0, boolean arg1)
{
// TODO Auto-generated method stub
return false;
}
@Override
public float getFloat(String arg0, float arg1)
{
// TODO Auto-generated method stub
return 0;
}
@Override
public int getInt(String arg0, int arg1)
{
// TODO Auto-generated method stub
return 0;
}
@Override
public long getLong(String arg0, long arg1)
{
// TODO Auto-generated method stub
return 0;
}
@Override
public String getString(String arg0, String arg1)
{
// TODO Auto-generated method stub
return null;
}
@Override
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener arg0)
{
// TODO Auto-generated method stub
}
@Override
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener arg0)
{
// TODO Auto-generated method stub
}
public static void readFromPersistentStorage(Context context)
@@ -209,6 +203,7 @@ public class Settings implements SharedPreferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
startServiceAtSystemBoot = prefs.getBoolean("startServiceAtSystemBoot", default_startServiceAtSystemBoot);
logToConsole = prefs.getBoolean("logToConsole", default_logToConsole);
writeLogFile = prefs.getBoolean("writeLogFile", default_writeLogFile);
boolean useTextToSpeech = false;
@@ -271,6 +266,7 @@ public class Settings implements SharedPreferences
activityDetectionRequiredProbability = Integer.parseInt(prefs.getString("activityDetectionRequiredProbability", String.valueOf(default_activityDetectionRequiredProbability)));
privacyLocationing = prefs.getBoolean("privacyLocationing", default_privacyLocationing);
uiTheme = Integer.parseInt(prefs.getString("uiTheme", String.valueOf(default_uiTheme)));
startScreen = Integer.parseInt(prefs.getString("startScreen", String.valueOf(default_startScreen)));
tabsPlacement = Integer.parseInt(prefs.getString("tabsPlacement", String.valueOf(default_tabsPlacement)));
@@ -349,6 +345,9 @@ public class Settings implements SharedPreferences
if(!prefs.contains("startServiceAtSystemBoot") || force)
editor.putBoolean("startServiceAtSystemBoot", default_startServiceAtSystemBoot);
if(!prefs.contains("logToConsole") || force)
editor.putBoolean("logToConsole", default_logToConsole);
if(!prefs.contains("writeLogFile") || force)
editor.putBoolean("writeLogFile", default_writeLogFile);
@@ -464,6 +463,9 @@ public class Settings implements SharedPreferences
if(!prefs.contains("privacyLocationing") || force)
editor.putBoolean("privacyLocationing", default_privacyLocationing);
if(!prefs.contains("uiTheme") || force)
editor.putString("uiTheme", String.valueOf(default_uiTheme));
if(!prefs.contains("startScreen") || force)
editor.putString("startScreen", String.valueOf(default_startScreen));
@@ -525,6 +527,7 @@ public class Settings implements SharedPreferences
Editor editor = prefs.edit();
editor.putBoolean("startServiceAtSystemBoot", startServiceAtSystemBoot);
editor.putBoolean("logToConsole", logToConsole);
editor.putBoolean("writeLogFile", writeLogFile);
// editor.putBoolean("useTextToSpeech", useTextToSpeech);
editor.putBoolean("useTextToSpeechOnNormal", useTextToSpeechOnNormal);
@@ -563,6 +566,7 @@ public class Settings implements SharedPreferences
editor.putString("activityDetectionFrequency", String.valueOf(activityDetectionFrequency));
editor.putString("activityDetectionRequiredProbability", String.valueOf(activityDetectionRequiredProbability));
editor.putBoolean("privacyLocationing", privacyLocationing);
editor.putString("uiTheme", String.valueOf(uiTheme));
editor.putString("startScreen", String.valueOf(startScreen));
editor.putString("tabsPlacement", String.valueOf(tabsPlacement));
editor.putBoolean("executeRulesAndProfilesWithSingleClick", executeRulesAndProfilesWithSingleClick);
@@ -619,7 +623,6 @@ public class Settings implements SharedPreferences
@Override
public Set<String> getStringSet(String arg0, Set<String> arg1)
{
// TODO Auto-generated method stub
return null;
}
}
@@ -2,6 +2,7 @@ package com.jens.automation2;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Collections;
public class TimeFrame
{
@@ -20,18 +21,19 @@ public class TimeFrame
public void setDayList(ArrayList<Integer> dayList)
{
this.dayList = dayList;
Collections.sort(dayList);
}
public void setDayListFromString(String dayListString)
{
// Log.i("Parsing", "Full string: " + dayListString);
char[] dayListCharArray = dayListString.toCharArray();
dayList = new ArrayList<Integer>();
for(char item : dayListCharArray)
{
// Log.i("Parsing", String.valueOf(item));
dayList.add(Integer.parseInt(String.valueOf(item)));
}
Collections.sort(dayList);
}
public TimeObject getTriggerTimeStart()
@@ -2,6 +2,7 @@ package com.jens.automation2;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.BatteryManager;
import android.os.Build;
import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
@@ -16,6 +17,7 @@ import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DateTimeListener;
import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener;
import com.jens.automation2.receivers.MediaPlayerListener;
@@ -24,6 +26,7 @@ import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.NotificationListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ProximityReceiver;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
@@ -65,6 +68,7 @@ public class Trigger
tethering,
subSystemState,
checkVariable,
proximity,
calendarEvent,
phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
@@ -126,6 +130,8 @@ public class Trigger
return context.getResources().getString(R.string.subSystemState);
case checkVariable:
return context.getResources().getString(R.string.checkVariable);
case proximity:
return context.getResources().getString(R.string.proximity);
case calendarEvent:
return context.getResources().getString(R.string.calendarEventCapital);
default:
@@ -134,6 +140,35 @@ public class Trigger
}
};
boolean triggerParameter; //if true->started event, if false->stopped
String triggerParameter2;
public static final String triggerParameter2Split = "tp2split";
Trigger_Enum triggerType = null;
PointOfInterest pointOfInterest = null;
TimeFrame timeFrame;
public static String triggerPhoneCallStateRinging = "ringing";
public static String triggerPhoneCallStateStarted = "started";
public static String triggerPhoneCallStateStopped = "stopped";
public static String triggerPhoneCallDirectionIncoming = "incoming";
public static String triggerPhoneCallDirectionOutgoing = "outgoing";
public static String triggerPhoneCallDirectionAny = "any";
public static String triggerPhoneCallNumberAny = "any";
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 static enum subSystemStates { wifi, bluetooth };
Rule parentRule = null;
@@ -257,9 +292,13 @@ public class Trigger
result = false;
break;
case calendarEvent:
if(!checkCalendarEvent())
if(!checkCalendarEvent(false))
result = false;
break;
case proximity:
if(!checkProximity())
result = false;
break;
default:
break;
}
@@ -292,17 +331,17 @@ public class Trigger
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
String[] params = this.getTriggerParameter2().split(triggerParameter2Split);
String[] params = this.getTriggerParameter2().split(triggerParameter2Split, -1);
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 = "";
// String requiredText;
// if (params.length >= 5)
String requiredText = params[4];
// else
// requiredText = "";
if(this.getTriggerParameter())
{
@@ -366,6 +405,14 @@ public class Trigger
else
Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5);
/*
We can only get here through the startup routine of the main service.
Because the notification did not come in at runtime, but was there
before we started, w need to take a record of it.
*/
if(NotificationListener.getLastNotification() == null)
NotificationListener.setLastNotification(sn);
foundMatch = true;
break;
}
@@ -553,16 +600,42 @@ public class Trigger
boolean checkHeadsetPlugged()
{
if(HeadphoneJackListener.isHeadsetConnected() != this.getTriggerParameter())
return false;
else
if(this.getHeadphoneType() != 2 && this.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType())
/*
Wenn verbunden:
- either -> true
- headphone -> true
- mikro -> wenn tatsächlich mikro
Wenn nicht verbunden:
- either -> true
- headphone -> true
- mikro -> true
*/
if(HeadphoneJackListener.isHeadsetConnected()) // connection detected
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), this.getParentRule().getName()), 3);
return false;
if(this.getTriggerParameter()) // connection demanded
{
if (this.getHeadphoneType() == 1)
{
if (this.getHeadphoneType() == HeadphoneJackListener.getHeadphoneType()) // Microphone demanded
return true;
else
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), this.getParentRule().getName()), 3);
}
else
return true;
}
}
else // disconnection detected
{
// Type doesn't matter here
if(!this.getTriggerParameter()) // disconnection demanded
return true;
}
return true;
return false;
}
boolean checkSubSystemState()
@@ -604,8 +677,14 @@ public class Trigger
{
if (map.containsKey(conditions[0]))
{
if (map.get(conditions[0]).equals(conditions[1]))
return true;
if(Miscellaneous.isRegularExpression(conditions[1]))
{
return (map.get(conditions[0]).matches(conditions[1]) == this.getTriggerParameter());
}
else
{
return (map.get(conditions[0]).equals(conditions[1]) == this.getTriggerParameter());
}
}
}
}
@@ -617,117 +696,162 @@ public class Trigger
return false;
}
boolean checkCalendarEvent()
public boolean checkCalendarEvent(boolean ignoreActive)
{
try
{
String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split);
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), false);
/*
0 = titleDirection
1 = title;
2 = descriptionDirection
3 = description
4 = eventLocationDirection
5 = eventLocation
6 = all day event
7 = availabilityList
8 = calendarList
*/
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), true,false);
for(CalendarReceiver.CalendarEvent event : calendarEvents)
{
boolean isActive = getTriggerParameter();
if(isActive != event.isCurrentlyActive())
{
Miscellaneous.logEvent("i", "CalendarCheck", "Event has to be currently active: " + String.valueOf(triggerParameter) + ", but is required otherwise.", 5);
if(!checkCalendarEvent(event, ignoreActive))
continue;
}
if(!StringUtils.isEmpty(conditions[1]))
{
if (!Miscellaneous.compare(conditions[0], conditions[1], event.title))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Title does not match.", 5);
continue;
}
}
if(!StringUtils.isEmpty(conditions[3]))
{
if (!Miscellaneous.compare(conditions[2], conditions[3], event.description))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Description does not match.", 5);
continue;
}
}
if(!StringUtils.isEmpty(conditions[5]))
{
if (!Miscellaneous.compare(conditions[4], conditions[5], event.location))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Location does not match.", 5);
continue;
}
}
if (Boolean.parseBoolean(conditions[6]) != event.allDay)
{
Miscellaneous.logEvent("i", "CalendarCheck", "All day setting does not match.", 5);
continue;
}
if(!StringUtils.isEmpty(conditions[7]))
{
String[] availabilities = conditions[7].split(ActivityManageTriggerCalendar.separator);
if (availabilities.length > 0)
{
if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Availability does not match.", 5);
continue;
}
}
}
if(!StringUtils.isEmpty(conditions[8]))
{
String[] calendars = conditions[8].split(ActivityManageTriggerCalendar.separator);
if (calendars.length > 0)
{
if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Calendar does not match.", 5);
continue;
}
}
}
// No contradictions found
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
return true;
}
// At this point none of the calendar items matches this trigger
// At this point none of the calendar items match this trigger
// If trigger demands no calendar event and there is absolutely no future event, we'll need to check for that.
if(calendarEvents.size() == 0)
{
if(getTriggerParameter() == false)
return true;
// Further criteria don't matter if there are no events to check
}
/*
If trigger demands no calendar event and there is absolutely no future event,
further criteria don't matter if there are no events to check.
*/
if(calendarEvents.size() == 0 && getTriggerParameter() == false)
return true;
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "checkVariable()", Log.getStackTraceString(e), 1);
Miscellaneous.logEvent("e", "checkCalendarEvent()", Log.getStackTraceString(e), 1);
}
return false;
}
public boolean checkCalendarEvent(CalendarReceiver.CalendarEvent event, boolean ignoreActive)
{
String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split);
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), true,false);
/*
0 = titleDir
1 = title
2 = descriptionDir
3 = description
4 = locationDir
5 = location
6 = evaluate all day event
7 = all day event
8 = evaluate reoccurring
9 = reoccurring
10 = availability list
11 = calendars list
*/
boolean isActive = getTriggerParameter();
if (!ignoreActive && isActive != event.isCurrentlyActive())
{
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event.title + " has to be currently active: " + String.valueOf(triggerParameter) + ", but is required otherwise.", 5);
return false;
}
if (!StringUtils.isEmpty(conditions[1]))
{
if (!Miscellaneous.compare(conditions[0], conditions[1], event.title))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Title of event " + event.title + " does not match.", 5);
return false;
}
}
if (!StringUtils.isEmpty(conditions[3]))
{
if (!Miscellaneous.compare(conditions[2], conditions[3], event.description))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Description " + event.title + " does not match.", 5);
return false;
}
}
if (!StringUtils.isEmpty(conditions[5]))
{
if (!Miscellaneous.compare(conditions[4], conditions[5], event.location))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Location " + event.title + " does not match.", 5);
return false;
}
}
if (Boolean.parseBoolean(conditions[6]))
{
if (Boolean.parseBoolean(conditions[7]) != event.allDay)
{
Miscellaneous.logEvent("i", "CalendarCheck", "All day setting " + event.title + " does not match.", 5);
return false;
}
}
if (Boolean.parseBoolean(conditions[8]))
{
if (Boolean.parseBoolean(conditions[9]) != event.reoccurring)
{
Miscellaneous.logEvent("i", "CalendarCheck", "Reoccurring setting " + event.title + " does not match.", 5);
return false;
}
}
if (!StringUtils.isEmpty(conditions[10]))
{
String[] availabilities = conditions[10].split(ActivityManageTriggerCalendar.separator);
if (availabilities.length > 0)
{
if (!Miscellaneous.arraySearch(availabilities, event.availability, false, true))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Availability of event " + event.title + " does not match.", 5);
return false;
}
}
}
if (!StringUtils.isEmpty(conditions[11]))
{
String[] calendars = conditions[11].split(ActivityManageTriggerCalendar.separator);
if (calendars.length > 0)
{
if (!Miscellaneous.arraySearch(calendars, String.valueOf(event.calendarId), false, true))
{
Miscellaneous.logEvent("i", "CalendarCheck", "Calendar of event " + event.title + " does not match.", 5);
return false;
}
}
}
// No contradictions found
Miscellaneous.logEvent("i", "CalendarCheck", "Event " + event + " matches.", 4);
return true;
}
public boolean checkProximity()
{
try
{
float currentLevel = ProximityReceiver.getProximityLevel();
String[] values = this.getTriggerParameter2().split(Trigger.triggerParameter2Split);
float part1 = Float.parseFloat(values[0]);
float part2 = Float.parseFloat(values[1]);
// Are we within the defined scope?
if(part1 <= currentLevel && currentLevel <= part2)
return true;
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "checkProximity()", Log.getStackTraceString(e), 1);
}
return false;
}
boolean checkBluetooth()
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Checking for bluetooth...", this.getParentRule().getName()), 4);
@@ -1067,13 +1191,13 @@ public class Trigger
{
if(!this.getTriggerParameter())
{
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule %1$s doesn't apply. We're entering POI: " + this.getPointOfInterest().getName() + ", not leaving it.", getParentRule().getName()), 4);
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. We're entering POI: " + this.getPointOfInterest().getName() + ", not leaving it.", getParentRule().getName()), 4);
return false;
}
}
else
{
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule %1$s doesn't apply. This is " + activePoi.getName() + ", not " + this.getPointOfInterest().getName() + ".", getParentRule().getName()), 4);
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. This is " + activePoi.getName() + ", not " + this.getPointOfInterest().getName() + ".", getParentRule().getName()), 4);
return false;
}
}
@@ -1091,24 +1215,21 @@ public class Trigger
// We are not at any POI. But if this trigger requires us NOT to be there, that may be fine.
if(this.getPointOfInterest() != null)
{
// if(activePoi.equals(oneTrigger.getPointOfInterest()))
// {
if(!this.getTriggerParameter())
{
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "We are not at POI \"" + this.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4);
}
else
{
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule %1$s doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", getParentRule().getName()), 3);
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", getParentRule().getName()), 3);
return false;
}
// }
}
else if(this.getPointOfInterest() == null)
{
if(!this.getTriggerParameter())
{
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule %1$s doesn't apply. We're at no POI. Rule specifies to be at anyone.", getParentRule().getName()), 5);
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. We're at no POI. Rule specifies to be at anyone.", getParentRule().getName()), 5);
return false;
}
}
@@ -1119,6 +1240,12 @@ public class Trigger
public boolean hasStateNotAppliedSinceLastRuleExecution()
{
/*
There is no easy event to tell when a tag has been disconnected again.
*/
if(getTriggerType().equals(Trigger_Enum.nfcTag))
return true;
if(getParentRule().getLastExecution() == null)
{
Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " has NOT applied since the parent rule\'s last activation.", 4);
@@ -1139,22 +1266,36 @@ public class Trigger
boolean checkCharging()
{
if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0)
if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0) // unknown state
{
return false; // unknown charging state, can't activate rule under these conditions
}
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1)
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1) // we are discharging
{
if(this.getTriggerParameter()) //rule says when charging, but we're currently discharging
return false;
if(!this.getTriggerParameter()) // rule says when charging, but we're currently discharging
return true;
}
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2)
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2) // we are charging
{
if(!this.getTriggerParameter()) //rule says when discharging, but we're currently charging
return false;
if(this.getTriggerParameter()) // rule says when discharging, but we're currently charging
{
// check charging type
if(StringUtils.isEmpty(getTriggerParameter2()))
return true;
else
{
int desiredType;
String[] typeParams = getTriggerParameter2().split(triggerParameter2Split, -1);
desiredType = Integer.parseInt(typeParams[0]);
if(desiredType == BatteryReceiver.batteryChargingTypeAny)
return true;
else if(desiredType == BatteryReceiver.getCurrentChargingType())
return true;
}
}
}
return true;
return false;
}
boolean checkTetheringActive()
@@ -1179,7 +1320,7 @@ public class Trigger
return false;
}
public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution)
public boolean checkDateTime(Object triggeringObject, boolean checkIfStateChangedSinceLastRuleExecution)
{
/*
* Use format known from Automation
@@ -1201,142 +1342,52 @@ public class Trigger
{
TimeFrame tf = new TimeFrame(getTriggerParameter2());
if(tf.getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK)))
if (DateTimeListener.areWeInTimeFrame(this, triggeringObject) != this.getTriggerParameter())
{
if(
// Regular case, start time is lower than end time
(
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
&&
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
)
)
if (triggerParameter)
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") outside of the specified TimeFrame (" + tf.toString() + "), but demanded is inside.", 5);
else
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + tf.toString() + "), but demanded is outside.", 4);
return false;
}
// We are inside or outside of the timeframe as demanded by the trigger
if (tf.getRepetition() > 0)
{
if (!isSupposedToRepeatSinceLastExecution(Calendar.getInstance()))
{
// We are in the timeframe
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + tf.toString() + ").", 4);
if(getTriggerParameter())
{
if(checkifStateChangedSinceLastRuleExecution)
{
/*
* Was there a target repetition time between last execution and now?
* If not -> return false.
*/
Calendar compareCal = Calendar.getInstance();
compareCal.setTimeInMillis(triggeringTime.getTime());
if(tf.getRepetition() > 0)
{
if(!isSupposedToRepeatSinceLastExecution(compareCal))
{
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repeated execution is not due, yet.", 4);
return false;
}
}
else
{
/*
* This is not a repeating rule. Have we left
* the relevant timeframe since the last run?
* Determine if it has ran today already. If yes
* return false because every rule that is not
* repeating can only be executed once per day.
*/
if(
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
&&
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
&&
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
)
{
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
return false;
}
}
}
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's what's specified. Trigger of rule " + this.getParentRule().getName() + " applies.", 4);
return true;
}
else
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's not what's specified. Trigger of rule " + this.getParentRule().getName() + " doesn't apply.", 4);
return false;
}
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repetition is not due, yet.", 4);
return false;
}
else
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + tf.toString() + ") because of the time.", 5);
if(!getTriggerParameter())
{
if(checkifStateChangedSinceLastRuleExecution)
{
/*
* Was there a target repetition time between last execution and now?
* If not -> return false.
*/
Calendar compareCal = Calendar.getInstance();
compareCal.setTimeInMillis(triggeringTime.getTime());
if(tf.getRepetition() > 0)
{
if(!isSupposedToRepeatSinceLastExecution(compareCal))
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repeated execution is not due, yet.", 4);
return false;
}
}
else
{
/*
* This is not a repeating rule. Have we left
* the relevant timeframe since the last run?
* Determine if it has ran today already. If yes
* return false because every rule that is not
* repeating can only be executed once per day.
*/
if(
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
&&
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
&&
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
)
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
return false;
}
}
}
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's what's specified. Trigger of rule " + this.getParentRule().getName() + " applies.", 5);
return true;
}
else
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's not what's specified. Trigger of rule " + this.getParentRule().getName() + " doesn't apply.", 5);
return false;
}
}
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " would apply because repetition is due.", 4);
}
else
{
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + tf.toString() + ") because of the day.", 5);
return false;
if (checkIfStateChangedSinceLastRuleExecution)
{
/*
* This is not a repeating rule. Have we left
* the relevant timeframe since the last run?
* Determine if it has ran today already. If yes
* return false because every rule that is not
* repeating can only be executed once per day.
*/
if (
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
&&
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
&&
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
)
{
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
return false;
}
}
}
}
catch(Exception e)
@@ -1344,43 +1395,8 @@ public class Trigger
Miscellaneous.logEvent("e", "Trigger", "There was an error while checking if the time based trigger applies: " + Log.getStackTraceString(e), 1);
return false;
}
}
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
{
Calendar calSet;
TimeObject setTime;
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
if(tf.getRepetition() > 0)
{
if(trigger.getTriggerParameter())
setTime = tf.getTriggerTimeStart();
else
setTime = tf.getTriggerTimeStop();
calSet = (Calendar) now.clone();
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
calSet.set(Calendar.MINUTE, setTime.getMinutes());
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
// If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1);
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calSet.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
long nextScheduleTimestamp = (calSet.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition());
Calendar calSchedule = Calendar.getInstance();
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
return calSchedule;
}
else
Miscellaneous.logEvent("i", "Trigger", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
return null;
return true;
}
boolean isSupposedToRepeatSinceLastExecution(Calendar now)
@@ -1390,7 +1406,7 @@ public class Trigger
// the simple stuff:
if(lastExec == null) // rule never run, go any way
if(lastExec == null) // rule never ran, go in any case
return true;
else if(tf.getRepetition() <= 0) // is not set to repeat at all
return false;
@@ -1401,41 +1417,17 @@ public class Trigger
* we're inside the specified timeframe.
*/
Calendar timeSupposedToRunNext = getNextRepeatedExecutionAfter(this, lastExec);
if(now.getTimeInMillis() > timeSupposedToRunNext.getTimeInMillis())
Calendar lastRepetitionNotExecutedYet = DateTimeListener.getNextRepeatedExecution(this);
lastRepetitionNotExecutedYet.add(Calendar.SECOND, (int) -(tf.getRepetition()));
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Last execution: " + Miscellaneous.formatDate(lastExec.getTime()), 5);
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "lastRepetitionNotExecutedYet: " + Miscellaneous.formatDate(lastRepetitionNotExecutedYet.getTime()), 5);
if(now.getTimeInMillis() > lastRepetitionNotExecutedYet.getTimeInMillis())
return true;
return false;
}
boolean triggerParameter; //if true->started event, if false->stopped
String triggerParameter2;
public static final String triggerParameter2Split = "tp2split";
Trigger_Enum triggerType = null;
PointOfInterest pointOfInterest = null;
TimeFrame timeFrame;
public static String triggerPhoneCallStateRinging = "ringing";
public static String triggerPhoneCallStateStarted = "started";
public static String triggerPhoneCallStateStopped = "stopped";
public static String triggerPhoneCallDirectionIncoming = "incoming";
public static String triggerPhoneCallDirectionOutgoing = "outgoing";
public static String triggerPhoneCallDirectionAny = "any";
public static String triggerPhoneCallNumberAny = "any";
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()
{
@@ -1593,6 +1585,20 @@ public class Trigger
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.stopping) + " ");
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.triggerCharging));
returnString.append(" (");
if(!StringUtils.isEmpty(getTriggerParameter2()))
{
String[] pieces = getTriggerParameter2().split(triggerParameter2Split, -1);
if(pieces[0].equals("0"))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.any));
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_AC)))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.charging_AC));
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_USB)))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.usb));
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_WIRELESS)))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.charging_wireless));
}
returnString.append(")");
break;
case batteryLevel:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.batteryLevel));
@@ -1728,7 +1734,7 @@ public class Trigger
try
{
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
if (ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), "com.google.android.gms.permission.ACTIVITY_RECOGNITION"))
if (ActivityPermissions.isPermissionDeclaredInManifest(Miscellaneous.getAnyContext(), "com.google.android.gms.permission.ACTIVITY_RECOGNITION"))
{
// This type doesn't have an activate/deactivate equivalent, at least not yet.
returnString.append(Miscellaneous.runMethodReflective(ActivityManageRule.activityDetectionClassPath, "getDescription", new Object[]{getActivityDetectionType()}));
@@ -1924,13 +1930,21 @@ public class Trigger
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.deactivated));
break;
case checkVariable:
if (triggerParameter2.contains(triggerParameter2Split))
if(triggerParameter)
{
String[] parts = triggerParameter2.split(triggerParameter2Split);
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.variableCheckString), parts[0], parts[1]));
if (triggerParameter2.contains(triggerParameter2Split))
{
String[] parts = triggerParameter2.split(triggerParameter2Split);
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.variableCheckString), parts[0], parts[1]));
}
else
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.variableCheckStringDeleted), triggerParameter2));
}
else
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.variableCheckStringDeleted), triggerParameter2));
{
String[] parts = triggerParameter2.split(triggerParameter2Split);
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.variableCheckStringNot), parts[0], parts[1]));
}
break;
case calendarEvent:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendarEvent));
@@ -1954,15 +1968,26 @@ public class Trigger
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendarDescription) + " " + conditions[4] + " " + conditions[5] + ", ");
if(Boolean.parseBoolean(conditions[6]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventTrue) + ", ");
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventFalse) + ", ");
{
if (Boolean.parseBoolean(conditions[7]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventTrue) + ", ");
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.allDayEventFalse) + ", ");
}
if (!StringUtils.isEmpty(conditions[7]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[7] + ", ");
if(Boolean.parseBoolean(conditions[8]))
{
if (Boolean.parseBoolean(conditions[9]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.reoccurringTrue) + ", ");
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.reoccurringFalse) + ", ");
}
if (!StringUtils.isEmpty(conditions[8]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[8]);
if (!StringUtils.isEmpty(conditions[10]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.availabilities) + " " + conditions[10] + ", ");
if (!StringUtils.isEmpty(conditions[11]))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.calendars) + " " + conditions[11]);
if (returnString.toString().endsWith(", "))
returnString.delete(returnString.length() - 2, returnString.length());
@@ -1970,6 +1995,10 @@ public class Trigger
returnString.append(")");
break;
case proximity:
String[] parts = triggerParameter2.split(triggerParameter2Split);
returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.proximityText), parts[0], parts[1]));
break;
default:
returnString.append("error");
break;
@@ -148,6 +148,13 @@ public class XmlFileInterface
serializer.startTag(null, "volumeNotifications");
serializer.text(String.valueOf(Profile.getProfileCollection().get(i).getVolumeNotifications()));
serializer.endTag(null, "volumeNotifications");
serializer.startTag(null, "changeVolumeRingtones");
serializer.text(String.valueOf(Profile.getProfileCollection().get(i).getChangeVolumeRingtones()));
serializer.endTag(null, "changeVolumeRingtones");//
serializer.startTag(null, "volumeRingtones");
serializer.text(String.valueOf(Profile.getProfileCollection().get(i).getVolumeRingtones()));
serializer.endTag(null, "volumeRingtones");
serializer.startTag(null, "changeVolumeAlarms");
serializer.text(String.valueOf(Profile.getProfileCollection().get(i).getChangeVolumeAlarms()));
@@ -619,8 +626,12 @@ public class XmlFileInterface
newProfile.setVolumeMusic(Integer.parseInt(readTag(parser, "volumeMusic")));
else if (name.equals("changeVolumeNotifications"))
newProfile.setChangeVolumeNotifications(Boolean.parseBoolean(readTag(parser, "changeVolumeNotifications")));
else if (name.equals("changeVolumeRingtones"))
newProfile.setChangeVolumeRingtones(Boolean.parseBoolean(readTag(parser, "changeVolumeRingtones")));
else if (name.equals("volumeNotifications"))
newProfile.setVolumeNotifications(Integer.parseInt(readTag(parser, "volumeNotifications")));
else if (name.equals("volumeRingtones"))
newProfile.setVolumeRingtones(Integer.parseInt(readTag(parser, "volumeRingtones")));
else if (name.equals("changeVolumeAlarms"))
newProfile.setChangeVolumeAlarms(Boolean.parseBoolean(readTag(parser, "changeVolumeAlarms")));
else if (name.equals("volumeAlarms"))
@@ -700,7 +711,7 @@ public class XmlFileInterface
private static Rule readRule(XmlPullParser parser) throws XmlPullParserException, IOException
{
/* FILE EXAMPE:
/* FILE EXAMPLE:
* *****************
* <Automation>
* <PointOfInterestCollection>
@@ -1084,7 +1095,7 @@ public class XmlFileInterface
private static Action readAction(XmlPullParser parser) throws IOException, XmlPullParserException
{
/* FILE EXAMPE:
/* FILE EXAMPLE:
* *****************
* <Automation>
* <PointOfInterestCollection>
@@ -1135,28 +1146,10 @@ public class XmlFileInterface
// *** deprecated
//else
if(actionNameString.equals("turnWifiOn"))
newAction.setAction(Action_Enum.turnWifiOn);
else if(actionNameString.equals("turnWifiOff"))
newAction.setAction(Action_Enum.turnWifiOff);
else if(actionNameString.equals("turnBluetoothOn"))
newAction.setAction(Action_Enum.turnBluetoothOn);
else if(actionNameString.equals("turnBluetoothOff"))
newAction.setAction(Action_Enum.turnBluetoothOff);
else if(actionNameString.equals("turnUsbTetheringOn"))
if(actionNameString.equals("turnUsbTetheringOn"))
newAction.setAction(Action_Enum.turnUsbTetheringOn);
else if(actionNameString.equals("turnUsbTetheringOff"))
newAction.setAction(Action_Enum.turnUsbTetheringOff);
else if(actionNameString.equals("turnWifiTetheringOn"))
newAction.setAction(Action_Enum.turnWifiTetheringOn);
else if(actionNameString.equals("turnWifiTetheringOff"))
newAction.setAction(Action_Enum.turnWifiTetheringOff);
else if(actionNameString.equals("enableScreenRotation"))
newAction.setAction(Action_Enum.enableScreenRotation);
else if(actionNameString.equals("disableScreenRotation"))
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);
@@ -1175,31 +1168,7 @@ public class XmlFileInterface
else if (name.equals("ActionParameter1"))
{
// exclusion for deprecated types
if(newAction.getAction().equals(Action_Enum.turnWifiOn))
{
newAction.setAction(Action_Enum.setWifi);
newAction.setParameter1(true);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnWifiOff))
{
newAction.setAction(Action_Enum.setWifi);
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnBluetoothOn))
{
newAction.setAction(Action_Enum.setBluetooth);
newAction.setParameter1(true);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnBluetoothOff))
{
newAction.setAction(Action_Enum.setBluetooth);
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnUsbTetheringOn))
if(newAction.getAction().equals(Action_Enum.turnUsbTetheringOn))
{
newAction.setAction(Action_Enum.setUsbTethering);
newAction.setParameter1(true);
@@ -1211,36 +1180,6 @@ public class XmlFileInterface
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnWifiTetheringOn))
{
newAction.setAction(Action_Enum.setWifiTethering);
newAction.setParameter1(true);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnWifiTetheringOff))
{
newAction.setAction(Action_Enum.setWifiTethering);
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.enableScreenRotation))
{
newAction.setAction(Action_Enum.setDisplayRotation);
newAction.setParameter1(true);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.disableScreenRotation))
{
newAction.setAction(Action_Enum.setDisplayRotation);
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.disableScreenRotation))
{
newAction.setAction(Action_Enum.setDisplayRotation);
newAction.setParameter1(false);
readTag(parser, "ActionParameter1"); //read the tag for the parser to head on
}
else if(newAction.getAction().equals(Action_Enum.turnScreenOnOrOff) && newAction.getParameter1())
{
/*
@@ -78,7 +78,7 @@ public class CellLocationChangedReceiver extends PhoneStateListener
{
for(Action action : Rule.getLastActivatedRule().getActionSet())
{
if(action.getAction() == Action.Action_Enum.turnWifiOn)
if(action.getAction() == Action.Action_Enum.setWifi && action.getParameter1())
{
// we will be using wifiReceiver, deactivate AccelerometerTimer if applicable
SensorActivity.stopAccelerometerTimer();
@@ -88,7 +88,7 @@ public class CellLocationChangedReceiver extends PhoneStateListener
catch(NullPointerException ne)
{
// Nothing to do, there is no last activated rule. Wifi hasn't been activated so we don't
// deactive accelerometer receiver.
// deactivate accelerometer receiver.
}
}
else
@@ -272,29 +272,23 @@ public class CellLocationChangedReceiver extends PhoneStateListener
locationListenerArmed = false;
Miscellaneous.logEvent("i", "LocationListener", "Disarmed location listener, accuracy reached", 4);
}
// Miscellaneous.logEvent("i", "LocationListener", "Giving update to POI class");
// PointOfInterest.positionUpdate(up2DateLocation, parentLocationProvider.parentService);
}
@Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
}
}
@@ -369,10 +363,10 @@ public class CellLocationChangedReceiver extends PhoneStateListener
// Miscellaneous.logEvent("i", "cellReceiver", "Not starting cellLocationListener because we have no data connection.", 4);
}
else
Miscellaneous.logEvent("w", "cellReceiver", "Wanted to activate CellLocationChangedReceiver, but Wifi-Receiver says not to.", 4);
Miscellaneous.logEvent("w", "cellReceiver", "Wanted to activate CellLocationChangedReceiver, but Wifi-Receiver says not to.", 5);
}
else
Miscellaneous.logEvent("i", "cellReceiver", "Not starting cellLocationListener because Airplane mode is active or SIM_STATE is not ready.", 4);
Miscellaneous.logEvent("i", "cellReceiver", "Not starting cellLocationListener because Airplane mode is active or SIM_STATE is not ready.", 5);
}
}
catch(Exception ex)
@@ -64,36 +64,36 @@ public class SensorActivity implements SensorEventListener
{
}
public void onSensorChanged(SensorEvent event)
{
// Device has been moved
public void onSensorChanged(SensorEvent event)
{
// Device has been moved
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
if(mInitialized)
{
deltaX = Math.abs(lastX-x);
deltaY = Math.abs(lastY-y);
deltaZ = Math.abs(lastZ-z);
//Wenn das jetzt einen gewissen Grenzwert übersteigt, müßten wir den CellListener wieder aktivieren
if(deltaX > Settings.accelerometerMovementThreshold | deltaY > Settings.accelerometerMovementThreshold | deltaZ > Settings.accelerometerMovementThreshold)
{
String text = "Device has been moved. " + String.valueOf(deltaX)+" / "+String.valueOf(deltaY)+" / "+String.valueOf(deltaZ);
Miscellaneous.logEvent("i", "Accelerometer", text, 5);
CellLocationChangedReceiver.resetFollowUpdate();
CellLocationChangedReceiver.startCellLocationChangedReceiver();
if(mInitialized)
{
deltaX = Math.abs(lastX-x);
deltaY = Math.abs(lastY-y);
deltaZ = Math.abs(lastZ-z);
// If that exceeds a certain delta we need to start CellLocationListener again
if(deltaX > Settings.accelerometerMovementThreshold | deltaY > Settings.accelerometerMovementThreshold | deltaZ > Settings.accelerometerMovementThreshold)
{
String text = "Device has been moved. " + String.valueOf(deltaX)+" / "+String.valueOf(deltaY)+" / "+String.valueOf(deltaZ);
Miscellaneous.logEvent("i", "Accelerometer", text, 5);
CellLocationChangedReceiver.resetFollowUpdate();
CellLocationChangedReceiver.startCellLocationChangedReceiver();
}
}
else
{
lastX = x;
lastY = y;
lastZ = z;
mInitialized = true;
}
}
}
else
{
lastX = x;
lastY = y;
lastZ = z;
mInitialized = true;
}
}
protected static void startAccelerometerReceiver()
{
@@ -17,6 +17,8 @@ import com.jens.automation2.Rule;
import com.jens.automation2.Settings;
import com.jens.automation2.Trigger;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
public class WifiBroadcastReceiver extends BroadcastReceiver
@@ -45,15 +47,15 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
public static void setLastWifiSsid(String newWifiSsid)
{
// Remove double quotes
// Remove double quotes that sometimes come
if(newWifiSsid.startsWith("\"") && newWifiSsid.endsWith("\""))
newWifiSsid = newWifiSsid.substring(1, newWifiSsid.length()-1);
// If it's a real name, not an empty string, it's stored as the last ssid
if(newWifiSsid.length() > 0)
{
if(newWifiSsid.equals(unknownSsidName))
WifiBroadcastReceiver.lastWifiSsidReal = lastWifiSsid;
if(!newWifiSsid.equals(unknownSsidName))
WifiBroadcastReceiver.lastWifiSsidReal = lastWifiSsid;
WifiBroadcastReceiver.lastWifiSsid = newWifiSsid;
}
@@ -74,6 +76,11 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
{
try
{
if(!StringUtils.isEmpty(intent.getAction()))
Miscellaneous.logEvent("i", "WifiReceiver", "Received signal with action \""+ intent.getAction() + "\".", 4);
else
Miscellaneous.logEvent("i", "WifiReceiver", "Received signal with empty action.", 4);
NetworkInfo myWifi = null;
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) // fired upon disconnection
@@ -98,8 +105,8 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
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
TODO: Every time the screen is turned on, we receive a "wifi has been connected"-event.
This is technically wrong and not really any change to when the screen was off. It has
to be filtered.
*/
}
@@ -130,7 +137,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
try
{
wasConnected = false;
Miscellaneous.logEvent("i", "WifiReceiver", String.format(context.getResources().getString(R.string.disconnectedFromWifi), getLastWifiSsid()) + " Switching to CellLocationChangedReceiver.", 3);
Miscellaneous.logEvent("i", "WifiReceiver", "Disconnected from wifi \"" + getLastWifiSsid() + "\". Switching to CellLocationChangedReceiver.", 3);
mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true;
CellLocationChangedReceiver.startCellLocationChangedReceiver();
lastConnectedState = false;
@@ -1,13 +1,14 @@
package com.jens.automation2.receivers;
import static android.os.BatteryManager.*;
import android.os.BatteryManager;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
@@ -19,12 +20,20 @@ import java.util.ArrayList;
public class BatteryReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
public static final int batteryChargingTypeAny = 0;
public static final int batteryChargingTypeAc = BatteryManager.BATTERY_PLUGGED_AC;
public static final int batteryChargingTypeUsb = BatteryManager.BATTERY_PLUGGED_USB;
public static final int batteryChargingTypeWireless = BatteryManager.BATTERY_PLUGGED_WIRELESS;
public static AutomationService automationServiceRef = null;
static int batteryLevel = -1; // initialize with a better value than this
static boolean usbHostConnected = false;
static boolean batteryReceiverActive = false;
static IntentFilter batteryIntentFilter = null;
static Intent batteryStatus = null;
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
private static int currentChargingType = 0; //AC, wireless, USB
static BroadcastReceiver batteryInfoReceiverInstance = null;
public static void startBatteryReceiver(final AutomationService automationServiceRef)
@@ -41,8 +50,6 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
batteryIntentFilter = new IntentFilter();
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_LOW);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
}
batteryStatus = automationServiceRef.registerReceiver(batteryInfoReceiverInstance, batteryIntentFilter);
@@ -79,8 +86,6 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
return batteryLevel;
}
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
public static int getCurrentChargingState()
{
return currentChargingState;
@@ -104,7 +109,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
{
try
{
batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
batteryLevel = intent.getIntExtra(EXTRA_LEVEL, -1);
// int scale = -1;
// int voltage = -1;
// int temp = -1;
@@ -114,31 +119,36 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
Log.i("Battery", "Level: " + String.valueOf(batteryLevel));
this.actionBatteryLevel(context);
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int statusPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
int status = intent.getIntExtra(EXTRA_STATUS, -1);
int statusPlugged = intent.getIntExtra(EXTRA_PLUGGED, -1);
Miscellaneous.logEvent("i", "BatteryReceiver", "Status: " + String.valueOf(statusPlugged), 5);
switch(statusPlugged)
{
case BatteryManager.BATTERY_PLUGGED_AC:
case BATTERY_PLUGGED_AC:
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.", 5);
this.actionCharging(context);
this.actionCharging(context, statusPlugged);
break;
case BatteryManager.BATTERY_PLUGGED_USB:
case BATTERY_PLUGGED_WIRELESS:
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
Miscellaneous.logEvent("i", "BatteryReceiver", "Wireless charging.", 5);
this.actionCharging(context, statusPlugged);
break;
case BATTERY_PLUGGED_USB:
this.actionUsbConnected(context);
break;
}
switch(status)
{
case BatteryManager.BATTERY_STATUS_CHARGING:
case BatteryManager.BATTERY_STATUS_FULL:
case BATTERY_STATUS_CHARGING:
case BATTERY_STATUS_FULL:
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.", 5);
this.actionCharging(context);
this.actionCharging(context, statusPlugged);
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
case BATTERY_STATUS_DISCHARGING:
case BATTERY_STATUS_NOT_CHARGING:
this.actionDischarging(context);
break;
}
@@ -155,28 +165,33 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
switch(currentChargingState)
{
case 0:
Miscellaneous.logEvent("w", "ChargingInfo", "Status of device charging was requested. Information isn't available, yet.", 4);
Miscellaneous.logEvent("w", "ChargingInfo", "Information isn't available, yet.", 4);
break;
case 1:
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is discharging.", 3);
Miscellaneous.logEvent("i", "ChargingInfo", "Device is discharging.", 3);
break;
case BatteryManager.BATTERY_STATUS_CHARGING:
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is charging.", 3);
case BATTERY_STATUS_CHARGING:
Miscellaneous.logEvent("i", "ChargingInfo", "Device is charging.", 3);
break;
}
return currentChargingState;
}
private void actionCharging(Context context)
public static int getCurrentChargingType()
{
if(currentChargingState != BatteryManager.BATTERY_STATUS_CHARGING) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
return currentChargingType;
}
private void actionCharging(Context context, int statusPlugged)
{
if(currentChargingState != BATTERY_STATUS_CHARGING) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.", 3);
currentChargingState = BatteryManager.BATTERY_STATUS_CHARGING;
//activate rule(s)
currentChargingState = BATTERY_STATUS_CHARGING;
currentChargingType = statusPlugged;
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
@@ -199,10 +214,10 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
private void actionDischarging(Context context)
{
if(currentChargingState != BatteryManager.BATTERY_STATUS_UNKNOWN) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
if(currentChargingState != BATTERY_STATUS_UNKNOWN) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is discharging.", 3);
currentChargingState = BatteryManager.BATTERY_STATUS_UNKNOWN;
currentChargingState = BATTERY_STATUS_UNKNOWN;
//activate rule(s)
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(false);
@@ -229,14 +244,13 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
// Toast.makeText(context, "Connected to computer.", Toast.LENGTH_LONG).show();
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.usb_host_connection);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(true);
for(Rule oneRule : ruleCandidates)
{
if(oneRule.getsGreenLight(context))
oneRule.activate(automationServiceRef, false);
}
this.actionCharging(context);
this.actionCharging(context, BATTERY_PLUGGED_USB);
}
}
@@ -286,7 +300,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
// actually monitores several
// actually monitors several
return new Trigger_Enum[] { Trigger_Enum.batteryLevel, Trigger_Enum.charging, Trigger_Enum.usb_host_connection };
}
}
@@ -7,6 +7,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
@@ -149,8 +150,6 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
{
return lhs.getName().compareTo(rhs.getName());
}
;
});
}
catch(NullPointerException e)
@@ -159,6 +158,12 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
returnArray = new BluetoothDevice[] {};
}
catch(SecurityException se)
{
Toast.makeText(Miscellaneous.getAnyContext(), Miscellaneous.getAnyContext().getResources().getString(R.string.permissionRequiredBluetooth), Toast.LENGTH_SHORT).show();
returnArray = new BluetoothDevice[] {};
}
return returnArray;
}
@@ -129,7 +129,10 @@ public class BroadcastListener extends android.content.BroadcastReceiver impleme
try
{
broadcastStatus = automationServiceRef.registerReceiver(broadcastReceiverInstance, broadcastIntentFilter);
if(Build.VERSION.SDK_INT >= 33)
broadcastStatus = automationServiceRef.registerReceiver(broadcastReceiverInstance, broadcastIntentFilter, Context.RECEIVER_EXPORTED);
else
broadcastStatus = automationServiceRef.registerReceiver(broadcastReceiverInstance, broadcastIntentFilter);
broadcastReceiverActive = true;
}
catch(Exception e)
@@ -9,9 +9,12 @@ import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.provider.CalendarContract;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
@@ -20,6 +23,7 @@ import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
@@ -29,7 +33,6 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
static CalendarReceiver calendarReceiverInstance = null;
static boolean calendarReceiverActive = false;
static IntentFilter calendarIntentFilter = null;
private static AutomationService automationServiceRef;
private static Intent calendarIntent = null;
public static final int AVAILABILITY_OUT_OF_OFFICE = 4;
@@ -38,12 +41,50 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
static List<AndroidCalendar> calendarsCache = null;
static List<CalendarEvent> calendarEventsCache = null;
static List<CalendarEvent> calendarEventsReoccurringCache = null;
// To determine for which events which rules have been executed
static List<RuleEventPair> calendarEventsUsed = new ArrayList<>();
static Timer timer = null;
static TimerTask timerTask = null;
static Calendar nextWakeup = null;
static AlarmManager alarmManager = null;
static boolean alarmHasChanged = false;
static boolean wakeupNeedsToBeScheduledOrRescheduled = false;
public static CalendarEvent getLastTriggeringEvent()
{
if(calendarEventsUsed.size() > 0)
{
return calendarEventsUsed.get(calendarEventsUsed.size() -1).event;
}
return null;
}
public static class RuleEventPair
{
Rule rule;
CalendarEvent event;
public RuleEventPair(Rule rule, CalendarEvent event)
{
this.rule = rule;
this.event = event;
}
}
public static void addUsedPair(RuleEventPair pair)
{
// Add pair only if it's not in the list already.
for(RuleEventPair usedPair : calendarEventsUsed)
{
if(usedPair.rule.equals(pair.rule) && usedPair.event.equals(pair.event))
return;
}
calendarEventsUsed.add(pair);
}
public static CalendarReceiver getInstance()
{
@@ -56,52 +97,43 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
@Override
public void onReceive(Context context, Intent intent)
{
Miscellaneous.logEvent("i", "CalendarReceiver", "Received " + intent.getAction(), 4);
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_PROVIDER_CHANGED))
{
Miscellaneous.logEvent("i", "CalendarReceiver", "Received " + intent.getAction(), 5);
Miscellaneous.logEvent("i", "CalendarReceiver", "Clearing calendar caches.", 4);
calendarsCache = null;
calendarEventsCache = null;
clearCaches();
checkForRules(context);
armOrRearmTimer();
routineAtAlarm();
}
else if(intent.getAction().equalsIgnoreCase(calendarAlarmAction))
{
Miscellaneous.logEvent("i", "AlarmReceiver", "Received alarm for calendar receiver.", 5);
routineAtAlarm();
}
}
private static void checkForRules(Context context)
static void checkForRules(Context context)
{
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
for(int i = 0; i < ruleCandidates.size(); i++)
for (int i = 0; i < ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
if (ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
}
}
@Override
public void startListener(AutomationService automationService)
public void startListener(AutomationService automationServiceRef)
{
if(!calendarReceiverActive)
{
if(calendarReceiverInstance == null)
calendarReceiverInstance = new CalendarReceiver();
startCalendarReceiver(automationServiceRef);
}
if(calendarIntentFilter == null)
{
calendarIntentFilter = new IntentFilter();
calendarIntentFilter.addAction(Intent.ACTION_PROVIDER_CHANGED);
// calendarIntentFilter.addDataScheme("content");
}
AutomationService.getInstance().registerReceiver(calendarReceiverInstance, calendarIntentFilter);
calendarReceiverActive = true;
}
static void clearCaches()
{
calendarsCache = null;
calendarEventsCache = null;
calendarEventsReoccurringCache = null;
}
@Override
@@ -115,6 +147,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
calendarReceiverInstance = null;
}
clearCaches();
calendarEventsUsed.clear();
calendarReceiverActive = false;
}
}
@@ -155,7 +190,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
public String location;
public String availability;
public Calendar start, end;
public boolean allDay;
public boolean allDay, reoccurring;
public boolean isCurrentlyActive()
{
@@ -167,7 +202,38 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
@Override
public String toString()
{
return title;
return "Title: " + title + ", location: " + location + ", description: " + description + ", start: " + Miscellaneous.formatDate(start.getTime()) + ", end: " + Miscellaneous.formatDate(end.getTime()) + ", is currently active: " + String.valueOf(isCurrentlyActive()) + ", all day: " + String.valueOf(allDay) + ", availability: " + availability;
}
@Override
public boolean equals(@Nullable Object obj)
{
try
{
CalendarEvent compareEvent = (CalendarEvent) obj;
return calendarId == compareEvent.calendarId
&&
eventId.equals(compareEvent.eventId)
&&
title.equals(compareEvent.title)
&&
description.equals(compareEvent.description)
&&
location.equals(compareEvent.location)
&&
availability.equals(compareEvent.availability)
&&
start.getTimeInMillis() == compareEvent.start.getTimeInMillis()
&&
end.getTimeInMillis() == compareEvent.end.getTimeInMillis()
&&
allDay == compareEvent.allDay;
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "CalendarReceiver compare()", Log.getStackTraceString(e), 5);
return false;
}
}
}
@@ -181,15 +247,14 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
cursor = context.getContentResolver().query(
Uri.parse("content://com.android.calendar/calendars"),
new String[]{ "_id", "calendar_displayName", "ownerAccount", },
new String[]{ CalendarContract.Calendars._ID, CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CalendarContract.Calendars.OWNER_ACCOUNT, },
null, null, null);
cursor.moveToFirst();
// fetching calendars name
String CNames[] = new String[cursor.getCount()];
List<AndroidCalendar> calendarlist = new ArrayList<>();
for (int i = 0; i < CNames.length; i++)
{
try
@@ -214,7 +279,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
return calendarsCache;
}
public static List<CalendarEvent> readCalendarEvents(Context context, boolean includePastEvents)
public static List<CalendarEvent> readCalendarEvents(Context context, boolean includeReoccurring, boolean includePastEvents)
{
if(calendarEventsCache == null)
{
@@ -224,7 +289,17 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
cursor = context.getContentResolver().query(
Uri.parse("content://com.android.calendar/events"),
new String[] { "calendar_id", "_id", "title", "description", "allDay", "dtstart", "dtend", "eventLocation", "availability" },
new String[] {
CalendarContract.Events.CALENDAR_ID,
CalendarContract.Events._ID,
CalendarContract.Events.TITLE,
CalendarContract.Events.DESCRIPTION,
CalendarContract.Events.ALL_DAY,
CalendarContract.Events.DTSTART,
CalendarContract.Events.DTEND,
CalendarContract.Events.EVENT_LOCATION,
CalendarContract.Events.AVAILABILITY
},
null, null, null);
cursor.moveToFirst();
@@ -257,6 +332,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
event.end = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(6)));
event.location = cursor.getString(7);
event.availability = cursor.getString(8);
event.reoccurring = false;
if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis())
calendarEventsCache.add(event);
@@ -271,6 +347,84 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
}
if(includeReoccurring && calendarEventsReoccurringCache == null)
{
calendarEventsReoccurringCache = new ArrayList<>();
Cursor cursor;
Calendar queryStart, queryEnd;
if(includePastEvents)
queryStart = Miscellaneous.calendarFromLong(0);
else
queryStart = Calendar.getInstance();
queryEnd = Calendar.getInstance();
queryEnd.add(Calendar.YEAR, 1);
cursor = context.getContentResolver().query(
Uri.parse("content://com.android.calendar/instances/when/" + queryStart.getTimeInMillis() + "/" + queryEnd.getTimeInMillis()),
new String[] {
CalendarContract.Instances.CALENDAR_ID,
CalendarContract.Instances._ID,
CalendarContract.Instances.TITLE,
CalendarContract.Instances.DESCRIPTION,
CalendarContract.Instances.ALL_DAY,
CalendarContract.Instances.BEGIN,
CalendarContract.Instances.END,
CalendarContract.Instances.EVENT_LOCATION,
CalendarContract.Instances.AVAILABILITY
},
null, null, null);
cursor.moveToFirst();
String CNames[] = new String[cursor.getCount()];
Calendar now = Calendar.getInstance();
for (int i = 0; i < CNames.length; i++)
{
try
{
CalendarEvent event = new CalendarEvent();
event.calendarId = Integer.parseInt(cursor.getString(0));
for(AndroidCalendar cal : readCalendars(context))
{
if(cal.calendarId == event.calendarId)
{
event.calendar = cal;
break;
}
}
event.eventId = cursor.getString(1);
event.title = cursor.getString(2);
event.description = cursor.getString(3);
event.allDay = cursor.getString(4).equals("1");
event.start = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(5)));
event.end = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(6)));
event.location = cursor.getString(7);
event.availability = cursor.getString(8);
event.reoccurring = true;
if(includePastEvents || event.end.getTimeInMillis() > now.getTimeInMillis())
{
// For the moment keeping separate records to some extent
calendarEventsReoccurringCache.add(event);
calendarEventsCache.add(event);
}
}
catch (Exception e)
{}
cursor.moveToNext();
}
if(cursor != null)
cursor.close();
}
return calendarEventsCache;
}
@@ -283,7 +437,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
armOrRearmTimer();
}
private static void armOrRearmTimer()
public static void armOrRearmTimer()
{
PendingIntent pi = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
@@ -291,7 +445,10 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
if (alarmManager == null)
{
alarmManager = (AlarmManager) Miscellaneous.getAnyContext().getSystemService(Context.ALARM_SERVICE);
}
if(pi == null)
{
Intent intent = new Intent(Miscellaneous.getAnyContext(), CalendarReceiver.class);
intent.setAction(calendarAlarmAction);
pi = PendingIntent.getBroadcast(AutomationService.getInstance(), 0, intent, 0);
@@ -318,12 +475,12 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
if(nextWakeup == null)
{
readCalendarEvents(Miscellaneous.getAnyContext(), false);
readCalendarEvents(Miscellaneous.getAnyContext(), true,false);
calculateNextWakeup();
}
// If it's now filled, go on
if(nextWakeup != null)
if(nextWakeup != null && wakeupNeedsToBeScheduledOrRescheduled)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
@@ -337,10 +494,9 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{
}
Miscellaneous.logEvent("i", "armOrRearmTimer()", "Setting calendar alarm for " + nextWakeup.toString(), 5);
Miscellaneous.logEvent("i", "armOrRearmTimer()", "Scheduling wakeup for calendar at " + Miscellaneous.formatDate(nextWakeup.getTime()), 4);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextWakeup.getTimeInMillis(), pi);
//alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextWakeup.getTimeInMillis(), pi);
wakeupNeedsToBeScheduledOrRescheduled = false;
}
}
else
@@ -351,46 +507,77 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
private static void calculateNextWakeup()
{
Calendar now = Calendar.getInstance();
if (nextWakeup != null && nextWakeup.getTimeInMillis() < now.getTimeInMillis())
nextWakeup = null;
List<CalendarEvent> events = readCalendarEvents(Miscellaneous.getAnyContext(), true, false);
List<CalendarEvent> events = readCalendarEvents(Miscellaneous.getAnyContext(), false);
if (events.size() > 0)
if(events.size() == 0)
{
Miscellaneous.logEvent("i", "calculateNextWakeup()", "Supposedly no future events in calendar. Reading again...", 4);
events = readCalendarEvents(Miscellaneous.getAnyContext(), true, false);
}
if (events.size() == 0)
{
Miscellaneous.logEvent("i", "calculateNextWakeup()", "No future events, nothing to schedule.", 4);
}
else
{
Miscellaneous.logEvent("i", "calculateNextWakeup()", String.valueOf(events.size()) + " future events in calendar. Checking if one applies.", 4);
List<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
List<Long> wakeUpCandidatesList = new ArrayList<>();
for (CalendarEvent event : events)
{
if (event.isCurrentlyActive())
for (Rule r : ruleCandidates)
{
if (nextWakeup == null || event.end.getTimeInMillis() < nextWakeup.getTimeInMillis())
for (Trigger t : r.getTriggerSet())
{
nextWakeup = event.end;
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing end of event " + event.title + " as next wakeup.", 5);
if(!alarmHasChanged)
alarmHasChanged = true;
}
}
else
{
if (nextWakeup == null || event.start.getTimeInMillis() < nextWakeup.getTimeInMillis())
{
nextWakeup = event.start;
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing start of event " + event.title + " as next wakeup.", 5);
if(!alarmHasChanged)
alarmHasChanged = true;
if (t.getTriggerType().equals(Trigger.Trigger_Enum.calendarEvent) && t.checkCalendarEvent(event, true))
{
/*
Device needs to wakeup at start AND end of events, no matter what is specified in triggers.
This is because we also need to know when a trigger doesn't apply anymore to make it
count for hasStateNotAppliedSinceLastRuleExecution().
Otherwise the same rule would not get executed again even after calendar events have come and gone.
*/
if(event.start.getTimeInMillis() > now.getTimeInMillis())
wakeUpCandidatesList.add(event.start.getTimeInMillis());
if(event.end.getTimeInMillis() > now.getTimeInMillis())
wakeUpCandidatesList.add(event.end.getTimeInMillis());
}
}
}
}
Collections.sort(wakeUpCandidatesList);
if(wakeUpCandidatesList.size() == 0)
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Not scheduling any calendar related wakeup as there are no future events that might match a configured trigger.", 4);
else
{
if (nextWakeup == null || nextWakeup.getTimeInMillis() != wakeUpCandidatesList.get(0))
{
Calendar newAlarm = Miscellaneous.calendarFromLong(wakeUpCandidatesList.get(0));
if (nextWakeup == null)
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was null.", 4);
else
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Chose " + Miscellaneous.formatDate(newAlarm.getTime()) + " as next wakeup for calendar triggers. Old was " + Miscellaneous.formatDate(nextWakeup.getTime()), 4);
nextWakeup = newAlarm;
if (!wakeupNeedsToBeScheduledOrRescheduled)
wakeupNeedsToBeScheduledOrRescheduled = true;
}
else
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Alarm " + Miscellaneous.formatDate(nextWakeup.getTime()) + " has been selected as next wakeup, but not rescheduling since this was not a change.", 4);
}
}
//else
// we expect to be called byOnReceive() when new items exist
}
public static void startCalendarReceiver(final AutomationService automationServiceRef)
{
if (!calendarReceiverActive)
{
CalendarReceiver.automationServiceRef = automationServiceRef;
if (calendarReceiverInstance == null)
calendarReceiverInstance = new CalendarReceiver();
@@ -402,11 +589,83 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
calendarIntentFilter.addDataAuthority("com.android.calendar", null);
}
calendarIntent = automationServiceRef.registerReceiver(calendarReceiverInstance, calendarIntentFilter);
if(Build.VERSION.SDK_INT >= 33)
calendarIntent = automationServiceRef.registerReceiver(calendarReceiverInstance, calendarIntentFilter, Context.RECEIVER_EXPORTED);
else
calendarIntent = automationServiceRef.registerReceiver(calendarReceiverInstance, calendarIntentFilter);
calendarReceiverActive = true;
armOrRearmTimer();
}
}
public static boolean mayRuleStillBeActivatedForPendingCalendarEvents(Rule rule)
{
for(RuleEventPair pair : calendarEventsUsed)
Miscellaneous.logEvent("i", "mayRuleStillBeActivatedForPendingCalendarEvents()", "Existing pair of " + pair.rule.getName() + " and " + pair.event, 5);
for(CalendarEvent event : readCalendarEvents(Miscellaneous.getAnyContext(), true,false))
{
for(Trigger t : rule.getTriggerSet())
{
if(t.getTriggerType().equals(Trigger.Trigger_Enum.calendarEvent) && t.checkCalendarEvent(event, false))
{
if (!hasEventBeenUsedInRule(rule, event))
{
/*
If there are multiple parallel calendar events and a rule has multiple
triggers of type calendar event, we don't want the rule to fire only once.
*/
if(rule.getAmountOfTriggersForType(Trigger.Trigger_Enum.calendarEvent) == 1)
{
Miscellaneous.logEvent("i", "mayRuleStillBeActivatedForPendingCalendarEvents()", "Rule " + rule.getName() + " has not been used in conjunction with event " + event, 4);
return true;
}
}
}
}
}
return false;
}
public static boolean hasEventBeenUsedInRule(Rule rule, CalendarEvent event)
{
for (RuleEventPair executedPair : calendarEventsUsed)
{
if (executedPair.rule.equals(rule) && executedPair.event.equals(event))
return true;
}
return false;
}
public static List<CalendarReceiver.CalendarEvent> getApplyingCalendarEvents(Rule rule)
{
List<CalendarReceiver.CalendarEvent> returnList = new ArrayList<>();
try
{
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance(), true,false);
for(Trigger t : rule.getTriggerSet())
{
if(t.getTriggerType().equals(Trigger.Trigger_Enum.calendarEvent))
{
for (CalendarReceiver.CalendarEvent event : calendarEvents)
{
if (t.checkCalendarEvent(event, false))
returnList.add(event);
}
}
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "getApplyingCalendarEvents()", Log.getStackTraceString(e), 1);
}
return returnList;
}
}
@@ -136,7 +136,12 @@ public class ConnectivityReceiver extends BroadcastReceiver implements Automatio
// Airplane mode status has changed.
Miscellaneous.logEvent("i", "Connectivity", "Airplane mode changed.", 2);
boolean isAirplaneMode = isAirplaneMode(context);
automationServiceRef.getLocationProvider().handleAirplaneMode(isAirplaneMode);
/*
If the user doesn't have any locations this service is probably off and therefore null.
*/
if(automationServiceRef.getLocationProvider() != null)
automationServiceRef.getLocationProvider().handleAirplaneMode(isAirplaneMode);
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.airplaneMode);
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode);
@@ -8,10 +8,10 @@ import android.content.Intent;
import android.os.Build;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.jens.automation2.AutomationService;
import com.jens.automation2.BuildConfig;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.TimeFrame;
@@ -19,23 +19,23 @@ import com.jens.automation2.TimeObject;
import com.jens.automation2.Trigger;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
public class DateTimeListener extends BroadcastReceiver implements AutomationListenerInterface
{
private static AutomationService automationServiceRef;
private static AlarmManager centralAlarmManagerInstance;
private static boolean alarmListenerActive = false;
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)
{
{
DateTimeListener.startAlarmListenerInternal(automationServiceRef);
}
public static void stopAlarmListener(Context context)
@@ -47,37 +47,37 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
{
return alarmListenerActive;
}
@Override
public void onReceive(Context context, Intent intent)
{
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
for(int i=0; i < allRulesWithNowInTimeFrame.size(); i++)
ArrayList<Rule> allRulesWithTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
for(int i=0; i < allRulesWithTimeFrame.size(); i++)
{
if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context))
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
if(allRulesWithTimeFrame.get(i).getsGreenLight(context))
allRulesWithTimeFrame.get(i).activate(automationServiceRef, false);
}
setAlarms();
setOrResetAlarms();
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static void setAlarms()
public static void setOrResetAlarms()
{
alarmCandidates.clear();
Calendar calNow = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
clearAlarms();
int i=0;
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
// allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame();
/*
* Take care of regular executions, no repetitions in between.
*/
@@ -191,18 +191,17 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
* 4. Take div result +1 and add this on top of starting time
* 5. Is this next possible execution still inside timeframe? Also consider timeframes spanning over midnight
*/
Calendar calSet;
Time setTime;
TimeFrame tf = new TimeFrame(oneTrigger.getTriggerParameter2());
if(tf.getRepetition() > 0)
{
if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext()))
{
Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow);
// if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext()))
// {
Calendar calSchedule = getNextRepeatedExecution(oneTrigger);
alarmCandidates.add(new ScheduleElement(calSchedule, "Rule " + oneRule.getName() + ", trigger " + oneTrigger.toString()));
}
// }
}
}
}
@@ -213,15 +212,15 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
}
}
}
scheduleNextAlarm();
}
private static void scheduleNextAlarm()
{
Long currentTime = System.currentTimeMillis();
long currentTime = System.currentTimeMillis();
ScheduleElement scheduleCandidate = null;
if(alarmCandidates.size() == 0)
{
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
@@ -235,46 +234,48 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
else if(alarmCandidates.size() > 1)
{
scheduleCandidate = alarmCandidates.get(0);
for(ScheduleElement alarmCandidate : alarmCandidates)
{
if(Math.abs(currentTime - alarmCandidate.time.getTimeInMillis()) < Math.abs(currentTime - scheduleCandidate.time.getTimeInMillis()))
scheduleCandidate = alarmCandidate;
}
}
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
else
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
centralAlarmManagerInstance.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
centralAlarmManagerInstance.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
else
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
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);
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
}
public static void clearAlarms()
{
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
for(int requestCode : requestCodeList)
{
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
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);
}
requestCodeList.clear();
}
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
{
if(!alarmListenerActive)
@@ -282,12 +283,11 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
DateTimeListener.automationServiceRef = givenAutomationServiceRef;
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
// alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
// alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, 0);
alarmListenerActive = true;
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
DateTimeListener.setAlarms();
DateTimeListener.setOrResetAlarms();
// // get a Calendar object with current time
// Calendar cal = Calendar.getInstance();
// // add 5 minutes to the calendar object
@@ -297,7 +297,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
else
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
}
private static void stopAlarmListenerInternal()
{
if(alarmListenerActive)
@@ -310,10 +310,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
else
Miscellaneous.logEvent("i", "AlarmListener", "Request to stop AlarmListener. But it's not running.", 5);
}
public static void reloadAlarms()
{
DateTimeListener.setAlarms();
}
@Override
public void startListener(AutomationService automationService)
{
@@ -371,46 +368,217 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
static int getNextDayIntForExecution(Trigger trigger)
{
Calendar calSet;
TimeObject setTime;
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
Calendar now = Calendar.getInstance();
if(tf.getDayList().contains(now.get(Calendar.DAY_OF_WEEK)))
return now.get(Calendar.DAY_OF_WEEK);
else
{
int dayNumberOfNextExecution = now.get(Calendar.DAY_OF_WEEK);
while(!tf.getDayList().contains(dayNumberOfNextExecution))
{
dayNumberOfNextExecution++;
if(dayNumberOfNextExecution > 6)
dayNumberOfNextExecution = 1;
}
return dayNumberOfNextExecution;
}
}
static int getDayDelta(Calendar now, int dayNumberOfNextExecution)
{
int result = dayNumberOfNextExecution - now.get(Calendar.DAY_OF_WEEK);
if(result >= 0)
return result;
else
return 6 + result;
}
@Nullable
@RequiresApi(api = Build.VERSION_CODES.N)
public static Calendar getNextRepeatedExecution(Trigger trigger)
{
Calendar now = Calendar.getInstance();
Miscellaneous.logEvent("i", "DateTimeListener", "Checking for next repetition execution after " + Miscellaneous.formatDate(now.getTime()), 5);
Calendar calculationStart, calSchedule = null;
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
if(tf.getRepetition() > 0)
{
if(trigger.getTriggerParameter())
setTime = tf.getTriggerTimeStart();
else
setTime = tf.getTriggerTimeStop();
calSet = (Calendar) now.clone();
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
calSet.set(Calendar.MINUTE, setTime.getMinutes());
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
// If the starting time is a day ahead remove 1 day.
if(calSet.getTimeInMillis() > now.getTimeInMillis())
calSet.add(Calendar.DAY_OF_MONTH, -1);
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calSet.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
long nextScheduleTimestamp = (calSet.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition());
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.
Are we inside of the timeframe or outside?
Inside -> is this demanded?
Yes:
If last execution known, calculate from it
If not known, calculate from start of timeframe
No:
Use end-time and add repetition
Outside? -> is this demanded?
Yes:
If last execution known, calculate from it
If not known, calculate from end of timeframe
No:
Use start-time and add repetition
*/
return calSchedule;
if(areWeInTimeFrame(trigger, new Date()))
{
if(trigger.getTriggerParameter())
{
if(trigger.getParentRule().getLastExecution() != null)
{
calculationStart = (Calendar) trigger.getParentRule().getLastExecution().clone();
}
else
{
calculationStart = (Calendar) now.clone();
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStart().getHours());
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStart().getMinutes());
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStart().getSeconds());
calculationStart.set(Calendar.MILLISECOND, 0);
}
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
calSchedule = (Calendar) calculationStart.clone();
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));
}
else
{
calculationStart = (Calendar) now.clone();
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStop().getHours());
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStop().getMinutes());
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStop().getSeconds());
calculationStart.set(Calendar.MILLISECOND, 0);
calSchedule = (Calendar) calculationStart.clone();
calSchedule.add(Calendar.SECOND, (int) tf.getRepetition());
}
}
else // not in timeframe
{
if (!trigger.getTriggerParameter())
{
if (trigger.getParentRule().getLastExecution() != null)
{
calculationStart = (Calendar) trigger.getParentRule().getLastExecution().clone();
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
calSchedule = (Calendar) calculationStart.clone();
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
return calSchedule;
}
else
{
calculationStart = (Calendar) now.clone();
if(tf.getDayList().contains(now.get(Calendar.DAY_OF_WEEK)))
{
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStop().getHours());
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStop().getMinutes());
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStop().getSeconds());
calculationStart.set(Calendar.MILLISECOND, 0);
calculationStart.add(Calendar.SECOND, (int) tf.getRepetition());
int dayDelta = getDayDelta(now, getNextDayIntForExecution(trigger));
calculationStart.add(Calendar.DAY_OF_WEEK, dayDelta);
}
calSchedule = (Calendar) calculationStart.clone();
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
return calSchedule;
}
/*long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
calSchedule = (Calendar) calculationStart.clone();
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));*/
}
else
{
calculationStart = (Calendar) now.clone();
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStart().getHours());
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStart().getMinutes());
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStart().getSeconds());
calculationStart.set(Calendar.MILLISECOND, 0);
calSchedule = (Calendar) calculationStart.clone();
calSchedule.add(Calendar.SECOND, (int) (tf.getRepetition()));
}
if (Miscellaneous.compareTimes(calSchedule, now) > 0)
calSchedule.add(Calendar.DAY_OF_MONTH, 1);
}
int dayDelta = getDayDelta(now, getNextDayIntForExecution(trigger));
calSchedule.add(Calendar.DAY_OF_WEEK, dayDelta);
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
}
else
Miscellaneous.logEvent("i", "DateTimeListener", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Trigger " + trigger.toString() + " is not configured to repeat.", 5);
return null;
return calSchedule;
}
public static boolean areWeInTimeFrame(Trigger trigger, Object triggeringObject)
{
/*
* Use format known from Automation
* 07:30:00/17:30:00/23456/300 <-- last parameter is optional: repetition in seconds
* Also required: inside or outside that interval
*/
Date triggeringTime;
// if(triggeringObject instanceof Date)
// triggeringTime = (Date)triggeringObject;
// else
triggeringTime = new Date();
String timeString = String.valueOf(triggeringTime.getHours()) + ":" + String.valueOf(triggeringTime.getMinutes()) + ":" + String.valueOf(triggeringTime.getSeconds());
TimeObject nowTime = TimeObject.valueOf(timeString);
Calendar calNow = Calendar.getInstance();
try
{
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
if(tf.getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK)))
{
if(
// Regular case, start time is lower than end time
(
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
&&
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
)
)
return true;
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "Trigger", "There was an error while checking if the time based trigger applies: " + Log.getStackTraceString(e), 1);
return false;
}
return false;
}
}
@@ -34,11 +34,11 @@ public class DeviceOrientationListener implements SensorEventListener, Automatio
static int sensorValueCounter = 0;
// Gravity rotational data
float gravity[];
float[] gravity;
// Magnetic rotational data
float magnetic[]; //for magnetic rotational data
float accels[] = new float[3];
float mags[] = 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;
@@ -53,12 +53,14 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati
{
try
{
/*Broadcast Action: Wired Headset plugged in or unplugged.
The intent will have the following extra values:
state - 0 for unplugged, 1 for plugged.
name - Headset type, human readable string
microphone - 1 if headset has a microphone, 0 otherwise*/
/*
Broadcast Action: Wired Headset plugged in or unplugged.
The intent will have the following extra values:
state - 0 for unplugged, 1 for plugged.
name - Headset type, human readable string
microphone - 1 if headset has a microphone, 0 otherwise
*/
int state = intent.getExtras().getInt("state");
String name = intent.getExtras().getString("name");
@@ -8,10 +8,10 @@ import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
@@ -36,18 +36,8 @@ public class NfcReceiver
public static NfcAdapter getNfcAdapter(Context context)
{
if(nfcAdapter == null)
{
if(Build.VERSION.SDK_INT <= 10)
{
// NFC not supported until after Gingerbread.
Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), 3);
return null;
}
else
{
nfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
}
nfcAdapter = NfcAdapter.getDefaultAdapter(context);
return nfcAdapter;
}
@@ -66,9 +56,9 @@ public class NfcReceiver
if(action == null)
{
Miscellaneous.logEvent("i", "NFC", "action=null", 5);
return;
return;
}
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
{
Miscellaneous.logEvent("i", "NFC", "ACTION_NDEF_DISCOVERED", 4);
@@ -91,28 +81,6 @@ public class NfcReceiver
new NdefReaderTask().execute(tag);
}
}
// else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action))
// {
//
// // In case we would still use the Tech Discovered Intent
// Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
// String[] techList = tag.getTechList();
// String searchedTech = Ndef.class.getName();
//
// for (String tech : techList)
// {
// if (searchedTech.equals(tech))
// {
// new NdefReaderTask().execute(tag);
// break;
// }
// }
// }
// else
// {
// // No NFC NDEF intent
// Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNoNdefIntentBut) + " " + action + ".", 5);
// }
}
@SuppressLint("NewApi")
@@ -307,7 +275,7 @@ public class NfcReceiver
{
format.connect();
format.format(completeMessageToWrite);
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
return true;
}
catch(IOException e)
@@ -322,7 +290,7 @@ public class NfcReceiver
Miscellaneous.logEvent("e", "NFC", "Error writing tag: " + Log.getStackTraceString(e), 2);
}
return false;
return false;
}
public static boolean checkNfcRequirements(Context context, boolean showErrorMessage)
@@ -334,15 +302,7 @@ public class NfcReceiver
return false;
}
else if(Build.VERSION.SDK_INT <= 10)
{
// NFC not supported until after Gingerbread.
if(showErrorMessage)
Toast.makeText(context, context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), Toast.LENGTH_LONG).show();
return false;
}
return true;
}
}
}
@@ -3,13 +3,13 @@ package com.jens.automation2.receivers;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.jens.automation2.AutomationService;
@@ -19,6 +19,7 @@ import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
// See here for reference: http://gmariotti.blogspot.com/2013/11/notificationlistenerservice-and-kitkat.html
@@ -26,8 +27,6 @@ import java.util.Calendar;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationListener extends NotificationListenerService// implements AutomationListenerInterface
{
static Calendar lastResponseToNotification = null;
static boolean listenerRunning = false;
static NotificationListener instance;
static SimpleNotification lastNotification = null;
@@ -43,13 +42,30 @@ public class NotificationListener extends NotificationListenerService// implemen
// 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 void setLastNotification(SimpleNotification notification)
{
lastNotification = notification;
}
public static SimpleNotification getLastNotification()
{
return lastNotification;
}
// To determine for which notifications which rules have been executed
static List<RuleNotificationPair> notificationUsed = new ArrayList<>();
public static class RuleNotificationPair
{
Rule rule;
SimpleNotification notification;
public RuleNotificationPair(Rule rule, SimpleNotification sn)
{
this.rule = rule;
this.notification = sn;
}
}
@Override
public void onCreate()
{
@@ -84,6 +100,7 @@ public class NotificationListener extends NotificationListenerService// implemen
synchronized boolean checkNotification(boolean created, StatusBarNotification sbn)
{
//TODO: Merge with function in Trigger class
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
{
lastNotification = convertNotificationToSimpleNotification(created, sbn);
@@ -129,13 +146,13 @@ public class NotificationListener extends NotificationListenerService// implemen
try
{
if (extras.containsKey(EXTRA_TEXT))
text = extras.getString(EXTRA_TEXT).toString();
text = String.valueOf(extras.getCharSequence(EXTRA_TEXT));
}
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();
text = String.valueOf(extras.getCharSequence(EXTRA_TEXT));
}
SimpleNotification returnNotification = new SimpleNotification();
@@ -215,6 +232,19 @@ public class NotificationListener extends NotificationListenerService// implemen
", text='" + text + '\'' +
'}';
}
@Override
public boolean equals(@Nullable Object obj)
{
return
this.publishTime.getTimeInMillis() == ((SimpleNotification)obj).publishTime.getTimeInMillis()
&&
this.app.equals(((SimpleNotification)obj).app)
&&
this.title.equals(((SimpleNotification)obj).title)
&&
this.text.equals(((SimpleNotification)obj).text);
}
}
@Override
@@ -235,7 +265,6 @@ public class NotificationListener extends NotificationListenerService// implemen
cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
else
cancelNotification(sbn.getKey());
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@@ -0,0 +1,162 @@
package com.jens.automation2.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.util.ArrayList;
public class ProximityReceiver implements AutomationListenerInterface
{
public static AutomationService automationServiceRef = null;
static float proximityLevel = -1; // initialize with a better value than this
static boolean proximityReceiverActive = false;
SensorManager sensorManager;
Sensor proximitySensor;
static ProximityReceiver proximityReceiverInstance = null;
public static float getProximityLevel()
{
return proximityLevel;
}
public static void startProximityReceiver(final AutomationService automationServiceRef)
{
if(!proximityReceiverActive)
{
ProximityReceiver.automationServiceRef = automationServiceRef;
if(proximityReceiverInstance == null)
proximityReceiverInstance = new ProximityReceiver();
proximityReceiverInstance.startListener(automationServiceRef);
proximityReceiverActive = true;
}
}
public static void stopProximityReceiver()
{
if(proximityReceiverActive)
{
if(proximityReceiverInstance != null)
{
proximityReceiverInstance = null;
}
proximityReceiverActive = false;
}
}
@Override
public void startListener(AutomationService automationService)
{
if(!proximityReceiverActive)
{
ProximityReceiver.automationServiceRef = automationServiceRef;
sensorManager = (SensorManager) automationService.getSystemService(Context.SENSOR_SERVICE);
// from sensor service we are
// calling proximity sensor
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
// handling the case if the proximity
// sensor is not present in users device.
if (proximitySensor == null)
{
Miscellaneous.logEvent("w", "No proximity sensor", "Device doesn\'t seem to have a proximity sensor.", 4);
}
else
{
// registering our sensor with sensor manager.
sensorManager.registerListener(proximitySensorEventListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
proximityReceiverActive = true;
}
}
@Override
public void stopListener(AutomationService automationService)
{
if(proximityReceiverActive)
{
if(proximityReceiverInstance != null)
{
if(proximitySensor != null)
sensorManager.unregisterListener(proximitySensorEventListener);
proximityReceiverInstance = null;
}
proximityReceiverActive = false;
}
}
SensorEventListener proximitySensorEventListener = new SensorEventListener()
{
@Override
public void onSensorChanged(SensorEvent sensorEvent)
{
// check if the sensor type is proximity sensor.
if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY)
{
proximityLevel = (int)sensorEvent.values[0];
Miscellaneous.logEvent("i", "Proximity", String.valueOf(proximityLevel), 5);
// if (sensorEvent.values[0] == 0)
// {
//// sensorStatusTV.setText("Near");
// }
// else
// {
//// sensorStatusTV.setText("Away");
// }
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.proximity);
for(Rule oneRule : ruleCandidates)
{
if(oneRule.getsGreenLight(automationServiceRef))
oneRule.activate(automationServiceRef, false);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i)
{
}
};
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission(ActivityPermissions.permissionNameProximity, Miscellaneous.getAnyContext());
}
@Override
public boolean isListenerRunning()
{
return proximityReceiverActive;
}
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
// actually monitors several
return new Trigger_Enum[] { Trigger_Enum.proximity };
}
}
@@ -76,12 +76,12 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
if(action.equals(Intent.ACTION_TIMEZONE_CHANGED))
{
Miscellaneous.logEvent("i", "TimeZoneListener", "Device timezone changed. Reloading alarms.", 3);
DateTimeListener.reloadAlarms();
DateTimeListener.setOrResetAlarms();
}
else if(action.equals(Intent.ACTION_TIME_CHANGED))
{
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 3);
DateTimeListener.reloadAlarms();
DateTimeListener.setOrResetAlarms();
}
}
@Override
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

+55 -22
View File
@@ -14,7 +14,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/etActivityOrActionPath"
@@ -45,7 +45,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/tvPoiTitle"
@@ -77,7 +77,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/tvRuleTitle"
@@ -88,33 +88,66 @@
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp" >
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp" >
<TextView
android:id="@+id/tvRuleHelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helpTextRules" />
android:id="@+id/tvRuleHelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helpTextRules" />
</LinearLayout>
<LinearLayout
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/tvProfileTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profiles"
android:layout_marginLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp" >
<TextView
android:id="@+id/tvProfileHelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helpTextProfiles" />
</LinearLayout>
<LinearLayout
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@string/toggableRules"
android:text="@string/toggleableRules"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
@@ -127,7 +160,7 @@
android:id="@+id/tvToggableHelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helpTextToggable" />
android:text="@string/helpTextToggleable" />
</LinearLayout>
@@ -136,7 +169,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/tvTimeFrameTitle"
android:layout_width="wrap_content"
@@ -164,7 +197,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:id="@+id/tvProcessMonitoringTitle"
@@ -192,7 +225,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -218,7 +251,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -31,6 +31,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/screenBrightGoogleComment" />
<Button
android:layout_marginTop="@dimen/default_margin"
android:id="@+id/bApplyBrightness"
@@ -180,6 +180,7 @@
android:id="@+id/rbNotificationDismissSimple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/simplyDismissNotification" />
<RadioButton
@@ -0,0 +1,171 @@
<?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" >
<TableLayout
android:id="@+id/tlTriggerUrlAuthentication"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/username" />
<EditText
android:id="@+id/etTriggerUrlUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:enabled="false"
android:inputType="text" >
</EditText>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password" />
<EditText
android:id="@+id/etTriggerUrlPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:enabled="false"
android:inputType="textPassword" >
</EditText>
</TableRow>
</TableLayout>
<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="wrap_content"
android:text="@string/target" />
<Spinner
android:id="@+id/spinnerSettingTarget"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/type" />
<Spinner
android:id="@+id/spinnerSettingDataType"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingName" />
<EditText
android:id="@+id/etSettingName"
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/settingValue" />
<EditText
android:id="@+id/etSettingValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:background="#aa000000" />
<TextView
android:id="@+id/tvSetSystemSettingExamples"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/examplesWriteSecureSettings" />
<TextView
android:id="@+id/tvSetSystemSettingNoticeWriteSecureSettings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/writeSecureSettingsNotice" />
<Button
android:id="@+id/bSaveSetSystemSetting"
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>
@@ -61,6 +61,12 @@
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/setVariableExplanation" />
<TextView
android:id="@+id/tvLegend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/urlLegend" />
<Button
android:id="@+id/bSaveVariable"
android:layout_marginTop="@dimen/default_margin"
@@ -293,7 +293,6 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvCurrentNfcIdValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/parameterName" />
@@ -336,6 +335,14 @@
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/intentParametersHint" />
<ListView
android:id="@+id/lvIntentPairs"
android:visibility="gone"
android:layout_marginVertical="@dimen/activity_horizontal_margin"
android:layout_width="match_parent"
android:layout_height="115dp"
android:layout_marginBottom="@dimen/default_margin" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -354,13 +361,6 @@
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/bSaveActionStartOtherActivity"
android:layout_width="wrap_content"
@@ -118,12 +118,98 @@
</RadioGroup>
<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>
<TextView
android:id="@+id/tvHttpParameterExplanation"
android:layout_span="2"
android:layout_marginBottom="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
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>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:background="#aa000000" />
<ListView
android:id="@+id/lvHttpParams"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="115dp"
android:layout_marginBottom="@dimen/default_margin" />
<Button
android:id="@+id/bAddHttpParam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addParameters" />
<ListView
android:id="@+id/lvTriggerUrlPostParameters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
</ListView>
android:layout_height="115dp"
android:visibility="gone" />
<ScrollView
android:layout_width="match_parent"
@@ -13,7 +13,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -157,9 +157,10 @@
android:layout_height="wrap_content"
android:text="@string/change" />
<TextView
android:id="@+id/tvNotificationsVolume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/volumeRingtoneNotifications"
android:text="@string/volumeNotifications"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="40dp" />
<SeekBar
@@ -167,6 +168,24 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp" />
<CheckBox
android:id="@+id/checkBoxChangeVolumeRingtones"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/change" />
<TextView
android:id="@+id/tvRingtoneVolume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/volumeRingtone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="40dp" />
<SeekBar
android:id="@+id/seekBarVolumeRingtones"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp" />
<CheckBox
android:id="@+id/checkBoxChangeVolumeAlarms"
@@ -337,6 +356,5 @@
</LinearLayout>
</LinearLayout>
</ScrollView>
</ScrollView>
@@ -15,7 +15,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -123,7 +123,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/barBackgroundColor"
android:background="@color/cardview_shadow_start_color"
android:orientation="horizontal">
<TextView
@@ -160,7 +160,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/barBackgroundColor"
android:background="@color/cardview_shadow_start_color"
android:orientation="horizontal">
<TextView
@@ -13,7 +13,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -16,6 +16,11 @@
android:textSize="25dp"
android:layout_marginBottom="@dimen/default_margin" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/calendarTriggerExecutionHints"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -175,6 +180,13 @@
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<CheckBox
android:id="@+id/chkCalendarEvaluateAllDayEvent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/evaluate"
android:checked="false"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
@@ -187,6 +199,39 @@
<CheckBox
android:id="@+id/chkCalendarAllDayEvent"
android:checked="false"
android:text="@string/allDayEventFalse"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<CheckBox
android:id="@+id/chkCalendarEvaluateReoccurring"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/evaluate"
android:checked="false"/>
<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/reoccurring" />
<CheckBox
android:id="@+id/chkCalendarReoccurring"
android:checked="false"
android:text="@string/reoccurringFalse"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
@@ -0,0 +1,123 @@
<?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/triggerCharging"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/triggerChargingComment" />
<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/rbChargingOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/charging" />
<RadioButton
android:id="@+id/rbChargingOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/notCharging" />
</RadioGroup>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:background="#aa000000" />
<TableRow>
<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/type" />
<RadioGroup>
<RadioButton
android:id="@+id/rbChargingTypeAny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/any" />
<RadioButton
android:id="@+id/rbChargingTypeAc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/charging_AC" />
<RadioButton
android:id="@+id/rbChargingTypeUsb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/usb" />
<RadioButton
android:id="@+id/rbChargingTypeWireless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/charging_wireless" />
</RadioGroup>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bTriggerChargingSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</LinearLayout>
</ScrollView>
@@ -31,7 +31,7 @@
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/VariableKey" />
@@ -47,21 +47,42 @@
android:layout_marginTop="@dimen/default_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/variableValue" />
android:text="@string/variableValue"
android:layout_marginRight="@dimen/default_margin" />
<EditText
android:id="@+id/etVariableValueTrigger"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/etVariableValueTrigger"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/mayUseRegularExpressions" />
</LinearLayout>
</TableRow>
</TableLayout>
<CheckBox
android:id="@+id/chkTriggerVariableDirection"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:text="@string/matches" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -16,7 +16,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -83,7 +83,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/barBackgroundColor" >
android:background="@color/cardview_shadow_start_color" >
<TextView
android:layout_width="wrap_content"
@@ -0,0 +1,112 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_margin="@dimen/default_margin">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/proximity"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:layout_marginBottom="@dimen/default_margin" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1" >
<TableRow>
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingRight="@dimen/default_margin"
android:text="@string/state"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.slider.RangeSlider
android:id="@+id/rsProximity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:valueFrom="0"
android:valueTo="10"
android:stepSize="0.1"
android:theme="@style/AppThemeCompat" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/close"
android:layout_alignParentLeft="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/far"
android:layout_alignParentRight="true"/>
</RelativeLayout>
</LinearLayout>
</TableRow>
</TableLayout>
<TextView
android:id="@+id/tvTriggerProximityHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:textColor="@color/red"
android:text="@string/deviceDoesntHaveProximitySensor" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/testArea"
android:textAppearance="@style/TextAppearance.AppCompat.Headline" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:text="@string/proximitySensorHint" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/testAreaProximityComment" />
<SeekBar
android:id="@+id/sbProximityTest"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvProximityCurrentValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bTriggerProximitySave"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</androidx.appcompat.widget.LinearLayoutCompat>

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