31 Commits

Author SHA1 Message Date
Jens
b0df3efa27 Merge branch 'tmp' into development 2022-08-17 22:42:12 +02:00
Jens
f99418fda3 started to adapt tethering trigger to check a specific type 2022-08-17 22:32:14 +02:00
e05a42f5d6 multidex 2022-08-06 02:13:39 +02:00
Jens
83a27dcfdb started to adapt tethering trigger to check a specific type 2022-07-27 23:00:34 +02:00
Jens
bdc89a855b translations and libraries updated 2022-07-27 22:11:35 +02:00
Jens
7ce203a679 translations and libraries updated 2022-07-27 22:10:07 +02:00
Jens
57bc666453 translations 2022-07-25 23:29:02 +02:00
c966981eae translations 2022-07-25 20:31:35 +02:00
Jens
7a05b9a95b device is starting-trigger enhanced 2022-07-24 22:50:11 +02:00
7fdbf74906 service is starting can be inverted 2022-07-24 19:53:45 +02:00
d17e8b70fe notification dismiss with button 2022-07-24 14:22:17 +02:00
Jens
f97bfbb732 close notification with button 2022-07-21 23:05:51 +02:00
937c6ffe1d Merge remote-tracking branch 'origin/development' into development
# Conflicts:
#	app/src/main/res/values/strings.xml
2022-07-19 17:58:41 +02:00
1ecc61452f notification dismiss with button 2022-07-19 17:57:47 +02:00
Jens
19fd2d098b wifi trigger needs location permission 2022-07-17 23:40:17 +02:00
Jens
d07c1a05e4 set wifi with root fix 2022-07-15 22:37:55 +02:00
Jens
f9f9b30116 su changes 2022-07-14 22:55:54 +02:00
d154a3d64f wifi trigger - enabled regex 2022-07-12 17:03:32 +02:00
Jens
eeb4f4a39e battery level trigger fixed 2022-07-11 22:56:43 +02:00
53e62068a5 close notification with button 2022-07-09 14:22:33 +02:00
922807d903 meta data changed 2022-07-07 20:40:29 +02:00
Jens
a7d294c115 translations 2022-07-04 23:02:46 +02:00
Jens
2d2fd901a1 translations 2022-07-04 22:57:07 +02:00
536a5e22f9 wakelock action 2022-07-02 12:46:34 +02:00
99faa2f7ef wakelock action 2022-07-02 01:38:39 +02:00
f3fac2f4e8 wakelock 2022-07-01 20:24:58 +02:00
Jens
b3b713e454 email tetx 2022-06-30 23:01:26 +02:00
Jens
b0d509aafe Merge remote-tracking branch 'origin/development-stable' into development
# Conflicts:
#	app/src/main/res/values-de/strings.xml
#	app/src/main/res/values/strings.xml
2022-06-27 23:04:33 +02:00
Jens
efb4919a1e regex where comparisons are made 2022-06-27 23:02:53 +02:00
Jens
7bc858fee3 number format fix attempt 2022-06-27 22:42:55 +02:00
647d5bd511 fix attempt number format 2022-06-27 20:07:06 +02:00
65 changed files with 1725 additions and 186 deletions

2
.gitignore vendored
View File

@@ -145,7 +145,7 @@ fabric.properties
# End of https://www.toptal.com/developers/gitignore/api/androidstudio
output-metadata.json
/app/app-release.apk
Automation_settings.xml
/app/googlePlayFlavor/

View File

@@ -13,6 +13,7 @@ android {
useLibrary 'org.apache.http.legacy'
versionCode 121
versionName "1.7.6"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -57,12 +58,20 @@ android {
checkReleaseBuilds false
}
namespace 'com.jens.automation2'
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'org.jetbrains:annotations:15.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:18.0.0'
implementation 'com.android.support:multidex:1.0.3'
implementation 'androidx.preference:preference:1.2.0'
apkFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
apkFlavorImplementation 'com.google.android.gms:play-services-location:18.0.0'
@@ -72,9 +81,9 @@ dependencies {
//implementation "androidx.security:security-crypto:1.0.0"
//implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+'
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'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@@ -1,20 +0,0 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.jens.automation2",
"variantName": "googlePlayFlavorRelease",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 121,
"versionName": "1.7.6-googlePlay",
"outputFile": "app-googlePlayFlavor-release.apk"
}
],
"elementType": "File"
}

View File

@@ -169,6 +169,8 @@
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity android:name=".ActivityManageActionWakeLock" />
<activity android:name=".ActivityManageTriggerSubSystemState" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@@ -396,7 +396,7 @@ public class Rule implements Comparable<Rule>
return true;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3);
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 4);
return false;
}

View File

@@ -167,6 +167,8 @@
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity android:name=".ActivityManageActionWakeLock" />
<activity android:name=".ActivityManageTriggerSubSystemState" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@@ -393,7 +393,7 @@ public class Rule implements Comparable<Rule>
return true;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3);
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 4);
return false;
}

View File

@@ -154,6 +154,8 @@
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity android:name=".ActivityManageActionWakeLock" />
<activity android:name=".ActivityManageTriggerSubSystemState" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@@ -396,7 +396,7 @@ public class Rule implements Comparable<Rule>
return true;
}
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3);
Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 4);
return false;
}

View File

@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name=".MainActivityTabs"
android:exported="false"
android:label="@string/title_activity_main_tabs"
android:theme="@style/AppTheme.NoActionBar" />
</application>
</manifest>

View File

@@ -53,6 +53,7 @@ public class Action
closeNotification,
sendBroadcast,
runExecutable,
wakelock,
sendTextMessage;
public String getFullName(Context context)
@@ -127,6 +128,8 @@ public class Action
return context.getResources().getString(R.string.sendBroadcast);
case runExecutable:
return context.getResources().getString(R.string.runExecutable);
case wakelock:
return context.getResources().getString(R.string.keepDeviceAwake);
default:
return "Unknown";
}
@@ -273,6 +276,9 @@ public class Action
case runExecutable:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.runExecutable));
break;
case wakelock:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.keepDeviceAwake) + " (" + String.valueOf(getParameter1()) + ")");
break;
default:
returnString.append(action.toString());
}
@@ -330,6 +336,14 @@ public class Action
if (parts.length > 4 && !StringUtils.isBlank(parts[4]))
returnString.append(", " + Miscellaneous.getAnyContext().getResources().getString(R.string.ifString) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.text) + " " + Trigger.getMatchString(parts[3]) + " " + parts[4]);
if(parts.length >= 6)
{
if(!parts[5].equals(ActivityManageActionCloseNotification.dismissRegularString))
{
returnString.append(" " + String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.withButton), parts[5]));
}
}
}
else if(this.getAction().equals(Action_Enum.setWifi))
{
@@ -485,7 +499,7 @@ public class Action
Actions.setUsbTethering(context, getParameter1(), toggleActionIfPossible);
break;
case setWifi:
Actions.WifiStuff.setWifi(context, getParameter1(), toggleActionIfPossible);
Actions.WifiStuff.setWifi(context, getParameter1(), getParameter2(), toggleActionIfPossible);
break;
case setWifiTethering:
Actions.setWifiTethering(context, getParameter1(), toggleActionIfPossible);
@@ -570,6 +584,12 @@ public class Action
else if(execParts.length == 2)
Actions.runExecutable(context, this.getParameter1(), execParts[0], execParts[1]);
break;
case wakelock:
if(this.getParameter1())
Actions.wakeLockStart(context, Long.parseLong(this.getParameter2()));
else
Actions.wakeLockStop();
break;
default:
Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3);
break;

View File

@@ -36,6 +36,7 @@ import android.view.KeyEvent;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.legacy.content.WakefulBroadcastReceiver;
import com.jens.automation2.actions.wifi_router.MyOnStartTetheringCallback;
import com.jens.automation2.actions.wifi_router.MyOreoWifiManager;
@@ -43,6 +44,7 @@ import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.NotificationListener;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
@@ -82,10 +84,6 @@ public class Actions
public static AutomationService automationServerRef;
public static Context context;
private static Intent playMusicIntent;
private static boolean suAvailable = false;
private static String suVersion = null;
private static String suVersionInternal = null;
private static List<String> suResult = null;
public final static String smsSeparator = "&sms&";
public final static String dummyPackageString = "dummyPkg239asd";
@@ -127,11 +125,14 @@ public class Actions
String myTitleDir = params[1];
String requiredTitle = params[2];
String myTextDir = params[3];
String requiredText;
if (params.length >= 5)
String requiredText = "";
String method = ActivityManageActionCloseNotification.dismissRegularString;
if(params.length >= 5)
requiredText = params[4];
else
requiredText = "";
if(params.length >= 6 && !params[5].equals(ActivityManageActionCloseNotification.dismissRegularString))
method = params[5];
for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications())
{
@@ -185,7 +186,12 @@ public class Actions
Miscellaneous.logEvent("i", "NotificationCloseCheck", "All criteria matches. Closing notification: " + sbn.getNotification().toString(), 3);
if(NotificationListener.getInstance() != null)
NotificationListener.getInstance().dismissNotification(sbn);
{
if(method == ActivityManageActionCloseNotification.dismissRegularString)
NotificationListener.getInstance().dismissNotification(sbn);
else
NotificationListener.getInstance().clickNotificationButton(sbn, method);
}
else
Miscellaneous.logEvent("i", "NotificationCloseCheck", "NotificationListener instance is null. Can\'t close notification.", 3);
}
@@ -214,9 +220,20 @@ public class Actions
public static class WifiStuff
{
public static Boolean setWifi(Context context, Boolean desiredState, boolean toggleActionIfPossible)
public static Boolean setWifi(Context context, Boolean desiredState, String parameter2, boolean toggleActionIfPossible)
{
if(context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q)
boolean forceUseRoot = false;
try
{
forceUseRoot = Boolean.parseBoolean(parameter2);
}
catch(Exception e)
{
}
if(context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q || forceUseRoot)
return setWifiWithRoot(context, desiredState, toggleActionIfPossible);
else
return setWifiOldFashioned(context, desiredState, toggleActionIfPossible);
@@ -252,8 +269,15 @@ public class Actions
{
Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState), 4);
if (desiredState && Settings.useWifiForPositioning)
WifiBroadcastReceiver.startWifiReceiver(automationServerRef.getLocationProvider());
try
{
if (desiredState && Settings.useWifiForPositioning)
WifiBroadcastReceiver.startWifiReceiver(automationServerRef.getLocationProvider());
}
catch(Exception e)
{
Miscellaneous.logEvent("w", "setWifiOldFashioned()", Log.getStackTraceString(e), 4);
}
WifiManager myWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -1864,6 +1888,12 @@ public class Actions
protected static boolean executeCommandViaSu(String[] commands)
{
boolean suAvailable = false;
String suVersion = null;
String suVersionInternal = null;
// List<String> suResult = null;
int suResult;
boolean success = false;
try
@@ -1873,17 +1903,30 @@ public class Actions
{
suVersion = Shell.SU.version(false);
suVersionInternal = Shell.SU.version(true);
suResult = Shell.SU.run(commands);
if (suResult != null)
Miscellaneous.logEvent("i", "executeCommandViaSu()", "suVersion: " + suVersion + ", suVersionInternal: " + suVersionInternal, 5);
// suResult = Shell.SU.run(commands);
suResult = Shell.Pool.SU.run(commands);
// if (suResult != null)
// success = true;
Miscellaneous.logEvent("i", "executeCommandViaSu()", "RC=" + String.valueOf(suResult), 3);
if(suResult == 0)
success = true;
}
else
Miscellaneous.logEvent("w", "executeCommandViaSu()", "su not available.", 4);
}
catch (Exception e)
{
success = false;
}
Miscellaneous.logEvent("i", "executeCommandViaSu()", "Returning " + String.valueOf(success), 4);
return success;
}
@@ -2092,4 +2135,61 @@ public class Actions
return false;
}
public final static int wakeLockTimeoutDisabled = -1;
static boolean wakeLockStopRequested = false;
public static void wakeLockStart(Context context, long duration)
{
Thread lockThread = new Thread(new Runnable()
{
@Override
public void run()
{
wakeLockStopRequested = false;
long waited = 0;
int step = 2000;
try
{
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
fullWakeLock.acquire(); // turn on
do
{
try
{
Thread.sleep(step); // turn on duration
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(duration > 0)
waited += step;
if(wakeLockStopRequested) //stop requested
Miscellaneous.logEvent("i", "WakeLockStart", "Stop requested.", 4);
}
while(!wakeLockStopRequested && (duration < 0 || waited <= duration));
fullWakeLock.release();
}
catch (Exception e)
{
}
}
});
lockThread.start();
}
public static void wakeLockStop()
{
Miscellaneous.logEvent("i", "WakeLockStart", "Requesting stop.", 4);
wakeLockStopRequested = true;
}
}

View File

@@ -16,9 +16,12 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
@@ -39,13 +42,16 @@ public class ActivityManageActionCloseNotification extends Activity
boolean edit = false;
ProgressDialog progressDialog = null;
EditText etNotificationTitle, etNotificationText;
EditText etNotificationTitle, etNotificationText, etNotificationDismissalButtonText;
Button bSelectApp, bSaveActionCloseNotification;
Spinner spinnerTitleDirection, spinnerTextDirection;
TextView tvSelectedApplication;
RadioButton rbNotificationDismissSimple, rbNotificationDismissButton;
private static List<PackageInfo> pInfos = null;
final static String dismissRegularString = "p0815DismissString";
private static String[] directions;
ArrayAdapter<String> directionSpinnerAdapter;
@@ -262,6 +268,9 @@ public class ActivityManageActionCloseNotification extends Activity
spinnerTitleDirection = (Spinner)findViewById(R.id.spinnerTitleDirection);
spinnerTextDirection = (Spinner)findViewById(R.id.spinnerTextDirection);
tvSelectedApplication = (TextView)findViewById(R.id.etActivityOrActionPath);
etNotificationDismissalButtonText = (EditText)findViewById(R.id.etNotificationDismissalButtonText);
rbNotificationDismissSimple = (RadioButton)findViewById(R.id.rbNotificationDismissSimple);
rbNotificationDismissButton = (RadioButton)findViewById(R.id.rbNotificationDismissButton);
directions = new String[] {
getResources().getString(R.string.directionStringEquals),
@@ -294,7 +303,7 @@ public class ActivityManageActionCloseNotification extends Activity
public void onClick(View v)
{
String app;
if(tvSelectedApplication.getText().toString().equalsIgnoreCase(getResources().getString(R.string.anyApp)))
if (tvSelectedApplication.getText().toString().equalsIgnoreCase(getResources().getString(R.string.anyApp)))
app = Trigger.anyAppString;
else
app = tvSelectedApplication.getText().toString();
@@ -305,34 +314,44 @@ public class ActivityManageActionCloseNotification extends Activity
String text = etNotificationText.getText().toString();
Intent responseData = new Intent();
if(edit)
{
// editedNotificationAction.setTriggerParameter(chkNotificationDirection.isChecked());
responseData.putExtra(ActivityManageRule.intentNameActionParameter2, app + Action.actionParameter2Split + titleDir + Action.actionParameter2Split + title + Action.actionParameter2Split + textDir + Action.actionParameter2Split + text);
ActivityManageActionCloseNotification.this.setResult(RESULT_OK, responseData);
}
String dismissMethod;
if (rbNotificationDismissSimple.isChecked())
dismissMethod = dismissRegularString;
else
{
// data.putExtra(intentNameNotificationDirection, chkNotificationDirection.isChecked());
responseData.putExtra(ActivityManageRule.intentNameActionParameter2,
app + Action.actionParameter2Split +
titleDir + Action.actionParameter2Split +
title + Action.actionParameter2Split +
textDir + Action.actionParameter2Split +
text
);
// data.putExtra(intentNameNotificationApp, app);
// data.putExtra(intentNameNotificationTitleDir, titleDir);
// data.putExtra(intentNameNotificationTitle, title);
// data.putExtra(intentNameNotificationTextDir, textDir);
// data.putExtra(intentNameNotificationText, text);
ActivityManageActionCloseNotification.this.setResult(RESULT_OK, responseData);
if(StringUtils.isEmpty(etNotificationDismissalButtonText.getText().toString()))
{
Toast.makeText(ActivityManageActionCloseNotification.this, getResources().getString(R.string.enterText), Toast.LENGTH_LONG).show();
return;
}
else
dismissMethod = etNotificationDismissalButtonText.getText().toString();
}
responseData.putExtra(ActivityManageRule.intentNameActionParameter2,
app + Action.actionParameter2Split +
titleDir + Action.actionParameter2Split +
title + Action.actionParameter2Split +
textDir + Action.actionParameter2Split +
text + Action.actionParameter2Split +
dismissMethod
);
ActivityManageActionCloseNotification.this.setResult(RESULT_OK, responseData);
finish();
}
});
rbNotificationDismissSimple.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
etNotificationDismissalButtonText.setEnabled(!b);
}
});
Intent i = getIntent();
if(!StringUtils.isBlank(i.getStringExtra(ActivityManageRule.intentNameActionParameter2)))
{
@@ -355,6 +374,24 @@ public class ActivityManageActionCloseNotification extends Activity
else
text = "";
/*
That's not reliable, yet. Last parameter may be empty, hence the method might
be incorrectly interpreted as a text notification text.
*/
if (params.length >= 6 && !params[5].equals(dismissRegularString))
{
rbNotificationDismissButton.setChecked(true);
etNotificationDismissalButtonText.setText(params[5]);
etNotificationDismissalButtonText.setEnabled(true);
}
else
{
rbNotificationDismissSimple.setChecked(true);
etNotificationDismissalButtonText.setText("");
etNotificationDismissalButtonText.setEnabled(false);
}
if(!app.equals(Trigger.anyAppString))
tvSelectedApplication.setText(app);

View File

@@ -172,6 +172,29 @@ public class ActivityManageActionSendBroadcast extends Activity
return;
}
switch(supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()])
{
case "int":
case "long":
case "short":
if(!Miscellaneous.isNumeric(etParameterValue.getText().toString()))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
break;
case "double":
case "float":
if(!Miscellaneous.isNumericDecimal(etParameterValue.getText().toString()))
{
Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
break;
default:
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
@@ -201,8 +224,10 @@ public class ActivityManageActionSendBroadcast extends Activity
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
if(supportedIntentTypes[arg2].equals("int") || supportedIntentTypes[arg2].equals("long") || supportedIntentTypes[arg2].equals("short"))
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
else if(supportedIntentTypes[arg2].equals("double") || supportedIntentTypes[arg2].equals("float"))
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
else
ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}

View File

@@ -153,6 +153,29 @@ public class ActivityManageActionStartActivity extends Activity
return;
}
switch(supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()])
{
case "int":
case "long":
case "short":
if(!Miscellaneous.isNumeric(etParameterValue.getText().toString()))
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
break;
case "double":
case "float":
if(!Miscellaneous.isNumericDecimal(etParameterValue.getText().toString()))
{
Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enter_a_number), Toast.LENGTH_LONG).show();
return;
}
break;
default:
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}
String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString();
intentPairList.add(param);
@@ -240,8 +263,10 @@ public class ActivityManageActionStartActivity extends Activity
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
if(supportedIntentTypes[arg2].equals("int") || supportedIntentTypes[arg2].equals("long") || supportedIntentTypes[arg2].equals("short"))
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
else if(supportedIntentTypes[arg2].equals("double") || supportedIntentTypes[arg2].equals("float"))
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
else
ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
}

View File

@@ -0,0 +1,99 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
public class ActivityManageActionWakeLock extends Activity
{
RadioButton rbWakeLockActivate, rbWakeLockDeactivate;
CheckBox chkWakeLockTimeout;
EditText etWakeLockDuration;
Button bSaveWakelock;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_action_wakelock);
rbWakeLockActivate = (RadioButton)findViewById(R.id.rbWakeLockActivate);
rbWakeLockDeactivate = (RadioButton)findViewById(R.id.rbWakeLockDeactivate);
chkWakeLockTimeout = (CheckBox)findViewById(R.id.chkWakeLockTimeout);
etWakeLockDuration = (EditText)findViewById(R.id.etWakeLockDuration);
bSaveWakelock = (Button)findViewById(R.id.bSaveWakelock);
etWakeLockDuration.setEnabled(chkWakeLockTimeout.isChecked());
chkWakeLockTimeout.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean wakeLockTimeoutSet)
{
etWakeLockDuration.setEnabled(wakeLockTimeoutSet);
if(wakeLockTimeoutSet)
etWakeLockDuration.setText(String.valueOf(Actions.wakeLockTimeoutDisabled));
}
});
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter1))
{
rbWakeLockActivate.setChecked(getIntent().getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true));
rbWakeLockDeactivate.setChecked(!getIntent().getBooleanExtra(ActivityManageRule.intentNameActionParameter1, false));
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
{
if(Miscellaneous.isNumeric(getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2)))
{
long timeout = Long.parseLong((getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2)));
chkWakeLockTimeout.setChecked(timeout != Actions.wakeLockTimeoutDisabled);
etWakeLockDuration.setText(String.valueOf(timeout));
}
else
{
chkWakeLockTimeout.setChecked(false);
etWakeLockDuration.setText(String.valueOf(Actions.wakeLockTimeoutDisabled));
}
}
}
bSaveWakelock.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
if(chkWakeLockTimeout.isChecked())
{
if((StringUtils.isEmpty(etWakeLockDuration.getText().toString()) || Integer.parseInt(etWakeLockDuration.getText().toString()) <= 0))
{
Toast.makeText(ActivityManageActionWakeLock.this, getResources().getString(R.string.enterAPositiveValidNonDecimalNumber), Toast.LENGTH_LONG).show();
return;
}
}
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameActionParameter1, rbWakeLockActivate.isChecked());
if(chkWakeLockTimeout.isChecked())
response.putExtra(ActivityManageRule.intentNameActionParameter2, etWakeLockDuration.getText().toString());
else
response.putExtra(ActivityManageRule.intentNameActionParameter2, String.valueOf(Actions.wakeLockTimeoutDisabled));
setResult(RESULT_OK, response);
finish();
}
});
}
}

View File

@@ -129,6 +129,10 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionSetWifiEdit = 816;
final static int requestCodeTriggerTetheringAdd = 817;
final static int requestCodeTriggerTetheringEdit = 818;
final static int requestCodeActionWakeLockAdd = 819;
final static int requestCodeActionWakeLockEdit = 820;
final static int requestCodeTriggerSubSystemStateAdd = 821;
final static int requestCodeTriggerSubSystemStateEdit = 822;
public static ActivityManageRule getInstance()
{
@@ -319,6 +323,12 @@ public class ActivityManageRule extends Activity
tetheringEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
startActivityForResult(tetheringEditor, requestCodeTriggerTetheringEdit);
break;
case subSystemState:
Intent subSystemStateEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerSubSystemState.class);
subSystemStateEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
subSystemStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(subSystemStateEditor, requestCodeTriggerSubSystemStateEdit);
break;
default:
break;
}
@@ -393,6 +403,12 @@ public class ActivityManageRule extends Activity
activityEditSendBroadcastIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditSendBroadcastIntent, requestCodeActionSendBroadcastEdit);
break;
case wakelock:
Intent activityEditWakeLockIntent = new Intent(ActivityManageRule.this, ActivityManageActionWakeLock.class);
activityEditWakeLockIntent.putExtra(intentNameActionParameter1, a.getParameter1());
activityEditWakeLockIntent.putExtra(intentNameActionParameter2, a.getParameter2());
startActivityForResult(activityEditWakeLockIntent, requestCodeActionWakeLockEdit);
break;
case runExecutable:
Intent activityEditRunExecutableIntent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class);
activityEditRunExecutableIntent.putExtra(intentNameActionParameter1, a.getParameter1());
@@ -577,6 +593,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.alarm));
else if(types[i].toString().equals(Trigger_Enum.tethering.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.router));
else if(types[i].toString().equals(Trigger_Enum.subSystemState.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.subsystemstate));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@@ -749,19 +767,22 @@ public class ActivityManageRule extends Activity
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.lockedCommentScreenMustBeOff), ActivityManageRule.this).show();
return;
}
else if(triggerType == Trigger_Enum.deviceStarts)
/*else if(triggerType == Trigger_Enum.deviceStarts)
{
newTrigger.setTriggerType(Trigger_Enum.deviceStarts);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
return;
}
else if(triggerType == Trigger_Enum.serviceStarts)
}*/
else if(triggerType == Trigger_Enum.deviceStarts || triggerType == Trigger_Enum.serviceStarts)
{
newTrigger.setTriggerType(Trigger_Enum.serviceStarts);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
return;
// newTrigger.setTriggerType(Trigger_Enum.serviceStarts);
// ruleToEdit.getTriggerSet().add(newTrigger);
booleanChoices = new String[]{getResources().getString(R.string.yes), getResources().getString(R.string.no)};
// refreshTriggerList();
// return;
}
else if(triggerType == Trigger_Enum.headsetPlugged)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
@@ -785,6 +806,13 @@ public class ActivityManageRule extends Activity
startActivityForResult(tetheringTriggerEditor, requestCodeTriggerTetheringAdd);
return;
}
else if(triggerType == Trigger_Enum.subSystemState)
{
newTrigger.setTriggerType(Trigger_Enum.subSystemState);
Intent subSystemStateTriggerEditor = new Intent(myContext, ActivityManageTriggerSubSystemState.class);
startActivityForResult(subSystemStateTriggerEditor, requestCodeTriggerSubSystemStateAdd);
return;
}
else
getTriggerParameterDialog(context, booleanChoices).show();
@@ -876,6 +904,7 @@ public class ActivityManageRule extends Activity
return alertDialog;
}
private AlertDialog getTriggerBatteryDialog(final Context myContext, final String[] choices)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
@@ -890,6 +919,7 @@ public class ActivityManageRule extends Activity
triggerBattery = (which+1);
newTrigger.setTriggerType(Trigger_Enum.batteryLevel);
newTrigger.setBatteryLevel(triggerBattery);
newTrigger.setTriggerParameter2(String.valueOf(triggerBattery));
// Log.i("test", newTrigger.toString());
// Log.i("test", String.valueOf(newTrigger.getBatteryLevel()));
ruleToEdit.getTriggerSet().add(newTrigger);
@@ -1551,6 +1581,17 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionWakeLockAdd)
{
if(resultCode == RESULT_OK)
{
newAction.setParentRule(ruleToEdit);
newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, false));
newAction.setParameter2(data.getStringExtra(intentNameActionParameter2));
ruleToEdit.getActionSet().add(newAction);
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionControlMediaAdd)
{
if(resultCode == RESULT_OK)
@@ -1620,6 +1661,21 @@ public class ActivityManageRule extends Activity
this.refreshActionList();
}
}
else if(requestCode == requestCodeActionWakeLockEdit)
{
if(resultCode == RESULT_OK)
{
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();
}
}
else if(requestCode == requestCodeActionRunExecutableEdit)
{
if(resultCode == RESULT_OK)
@@ -1817,6 +1873,17 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerSubSystemStateAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
newTrigger.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerTetheringEdit)
{
if(resultCode == RESULT_OK)
@@ -1829,6 +1896,19 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerSubSystemStateEdit)
{
if(resultCode == RESULT_OK)
{
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.subSystemState);
editedTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
editedTrigger.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
}
protected AlertDialog getActionTypeDialog()
@@ -1884,6 +1964,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Action_Enum.sendBroadcast.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
else if(types[i].toString().equals(Action_Enum.wakelock.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.coffee));
else if(types[i].toString().equals(Action_Enum.runExecutable.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.script));
else if(types[i].toString().equals(Action_Enum.sendTextMessage.toString()))
@@ -2058,6 +2140,12 @@ public class ActivityManageRule extends Activity
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class);
startActivityForResult(intent, requestCodeActionRunExecutableAdd);
}
else if(Action.getActionTypesAsArray()[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()))
{
newAction.setAction(Action_Enum.controlMediaPlayback);

View File

@@ -0,0 +1,72 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import androidx.annotation.Nullable;
import com.jens.automation2.Trigger.subSystemStates;
public class ActivityManageTriggerSubSystemState extends Activity
{
RadioButton rbSubSystemStateWifi, rbSubSystemStateBluetooth;
RadioButton rbSubSystemStateEnabled, rbSubSystemStateDisabled;
Button bSubSystemStateSave;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_trigger_subsystemstate);
rbSubSystemStateWifi = (RadioButton)findViewById(R.id.rbSubSystemStateWifi);
rbSubSystemStateBluetooth = (RadioButton)findViewById(R.id.rbSubSystemStateBluetooth);
rbSubSystemStateEnabled = (RadioButton)findViewById(R.id.rbSubSystemStateEnabled);
rbSubSystemStateDisabled = (RadioButton)findViewById(R.id.rbSubSystemStateDisabled);
bSubSystemStateSave = (Button)findViewById(R.id.bSubSystemStateSave);
if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter1) && getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
subSystemStates desiredState = subSystemStates.valueOf(getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
switch(desiredState)
{
case wifi:
rbSubSystemStateWifi.setChecked(true);
break;
case bluetooth:
rbSubSystemStateBluetooth.setChecked(true);
break;
default:
}
if(getIntent().getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true))
rbSubSystemStateEnabled.setChecked(true);
else
rbSubSystemStateDisabled.setChecked(true);
}
bSubSystemStateSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent data = new Intent();
data.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbSubSystemStateEnabled.isChecked());
if(rbSubSystemStateWifi.isChecked())
data.putExtra(ActivityManageRule.intentNameTriggerParameter2, subSystemStates.wifi.name());
else if(rbSubSystemStateBluetooth.isChecked())
data.putExtra(ActivityManageRule.intentNameTriggerParameter2, subSystemStates.bluetooth.name());
ActivityManageTriggerSubSystemState.this.setResult(RESULT_OK, data);
finish();
}
});
}
}

View File

@@ -9,11 +9,19 @@ import android.widget.RadioButton;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
public class ActivityManageTriggerTethering extends Activity
{
RadioButton rbTetheringOn, rbTetheringOff;
RadioButton rbTetheringOn, rbTetheringOff, rbTetheringTypeAny, rbTetheringTypeWifi, rbTetheringTypeBluetooth, rbTetheringTypeUsb, rbTetheringTypeCable;
Button bTriggerTetheringSave;
public final static String tetheringTypeAny = "tetheringTypeAny";
public final static String tetheringTypeWifi = "tetheringTypeWifi";
public final static String tetheringTypeBluetooth = "tetheringTypeBluetooth";
public final static String tetheringTypeUsb = "tetheringTypeUsb";
public final static String tetheringTypeCable = "tetheringTypeCable";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
@@ -22,6 +30,11 @@ public class ActivityManageTriggerTethering extends Activity
rbTetheringOn = (RadioButton) findViewById(R.id.rbTetheringOn);
rbTetheringOff = (RadioButton)findViewById(R.id.rbTetheringOff);
rbTetheringTypeAny = (RadioButton) findViewById(R.id.rbTetheringTypeAny);
rbTetheringTypeWifi = (RadioButton) findViewById(R.id.rbTetheringTypeWifi);
rbTetheringTypeBluetooth = (RadioButton) findViewById(R.id.rbTetheringTypeBluetooth);
rbTetheringTypeUsb = (RadioButton) findViewById(R.id.rbTetheringTypeUsb);
rbTetheringTypeCable = (RadioButton) findViewById(R.id.rbTetheringTypeCable);
bTriggerTetheringSave = (Button) findViewById(R.id.bTriggerTetheringSave);
Intent input = getIntent();
@@ -31,6 +44,31 @@ public class ActivityManageTriggerTethering extends Activity
rbTetheringOff.setChecked(!input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
}
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
String type = input.getStringExtra(ActivityManageRule.intentNameTriggerParameter2);
if(!StringUtils.isEmpty(type))
{
switch(type)
{
case tetheringTypeAny:
rbTetheringTypeAny.setChecked(true);
case tetheringTypeWifi:
rbTetheringTypeWifi.setChecked(true);
case tetheringTypeBluetooth:
rbTetheringTypeBluetooth.setChecked(true);
case tetheringTypeUsb:
rbTetheringTypeUsb.setChecked(true);
case tetheringTypeCable:
rbTetheringTypeCable.setChecked(true);
default:
}
}
}
else
rbTetheringTypeAny.setChecked(true);
bTriggerTetheringSave.setOnClickListener(new View.OnClickListener()
{
@Override
@@ -38,6 +76,18 @@ public class ActivityManageTriggerTethering extends Activity
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbTetheringOn.isChecked());
if(rbTetheringTypeAny.isChecked())
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, tetheringTypeAny);
else if(rbTetheringTypeWifi.isChecked())
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, tetheringTypeWifi);
else if(rbTetheringTypeBluetooth.isChecked())
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, tetheringTypeBluetooth);
else if(rbTetheringTypeUsb.isChecked())
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, tetheringTypeUsb);
else if(rbTetheringTypeCable.isChecked())
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, tetheringTypeCable);
setResult(RESULT_OK, response);
finish();
}

View File

@@ -20,15 +20,13 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
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.jens.automation2.receivers.BluetoothReceiver;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -41,10 +39,11 @@ public class ActivityManageTriggerWifi extends Activity
RadioButton rbTriggerWifiConnected, rbTriggerWifiDisconnected;
EditText etTriggerWifiName;
Spinner spinnerWifiList;
Button btriggerWifiSave, bLoadWifiList;
Button bTriggerWifiSave, bLoadWifiList;
List<String> wifiList = new ArrayList<>();
ArrayAdapter<String> wifiSpinnerAdapter;
private final static int requestCodeLocationPermission = 124;
TextView tvWifiTriggerNameLocationNotice;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
@@ -56,13 +55,21 @@ public class ActivityManageTriggerWifi extends Activity
rbTriggerWifiDisconnected = (RadioButton) findViewById(R.id.rbTriggerWifiDisconnected);
etTriggerWifiName = (EditText) findViewById(R.id.etTriggerWifiName);
spinnerWifiList = (Spinner) findViewById(R.id.spinnerWifiList);
btriggerWifiSave = (Button) findViewById(R.id.btriggerWifiSave);
bTriggerWifiSave = (Button) findViewById(R.id.bTriggerWifiSave);
bLoadWifiList = (Button) findViewById(R.id.bLoadWifiList);
tvWifiTriggerNameLocationNotice = (TextView)findViewById(R.id.tvWifiTriggerNameLocationNotice);
wifiSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, wifiList);
spinnerWifiList.setAdapter(wifiSpinnerAdapter);
spinnerWifiList.setEnabled(false); // bug in Android; this only works when done in code, not in xml
if(
Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 29
&&
!ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
tvWifiTriggerNameLocationNotice.setVisibility(View.VISIBLE);
if (getIntent().hasExtra("edit"))
{
boolean connected = getIntent().getBooleanExtra("wifiState", false);
@@ -74,7 +81,7 @@ public class ActivityManageTriggerWifi extends Activity
etTriggerWifiName.setText(wifiName);
}
btriggerWifiSave.setOnClickListener(new View.OnClickListener()
bTriggerWifiSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)

View File

@@ -509,6 +509,12 @@ public class ActivityPermissions extends Activity
case wifiConnection:
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACCESS_WIFI_STATE, requiredPermissions);
if(
Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 29
&&
isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
addToArrayListUnique(Manifest.permission.ACCESS_BACKGROUND_LOCATION, requiredPermissions);
break;
case notification:
addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions);

View File

@@ -24,4 +24,4 @@ public class ActivitySettings extends PreferenceActivity
chkPrefUpdateCheck.setEnabled(true);
}
}
}
}

View File

@@ -473,6 +473,7 @@ public class AutomationService extends Service implements OnInitListener
PackageReplacedReceiver.setHasServiceBeenRunning(false, this);
centralInstance = null;
Settings.serviceStartDone = false;
}
protected static Builder createDefaultNotificationBuilderOld()

View File

@@ -0,0 +1,49 @@
package com.jens.automation2;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.jens.automation2.ui.main.SectionsPagerAdapter;
import com.jens.automation2.databinding.ActivityMainTabsBinding;
public class MainActivityTabs extends AppCompatActivity
{
private ActivityMainTabsBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
binding = ActivityMainTabsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = binding.viewPager;
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
tabs.setupWithViewPager(viewPager);
FloatingActionButton fab = binding.fab;
fab.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}

View File

@@ -476,7 +476,10 @@ public class Miscellaneous extends Service
switch(direction)
{
case Trigger.directionEquals:
return haystack.equalsIgnoreCase(needle);
if(Miscellaneous.isRegularExpression(needle))
return haystack.matches(needle);
else
return haystack.equalsIgnoreCase(needle);
case Trigger.directionNotEquals:
return !haystack.equalsIgnoreCase(needle);
case Trigger.directionContains:
@@ -788,11 +791,27 @@ public class Miscellaneous extends Service
return executedSuccesfully;
}
public static boolean isNumericDecimal(String strNum)
{
if (strNum == null)
{
return false;
}
try
{
double d = Double.parseDouble(strNum);
}
catch (NumberFormatException nfe)
{
return false;
}
return true;
}
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
/**
* Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
@@ -1753,13 +1772,12 @@ public class Miscellaneous extends Service
public static boolean comparePhoneNumbers(String number1, String number2)
{
/* To be activated when Android S SDK comes out
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.Q)
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.S)
{
TelephonyManager tm = (TelephonyManager)Miscellaneous.getAnyContext().getSystemService(Context.TELEPHONY_SERVICE);
return PhoneNumberUtils.areSamePhoneNumber(number1, number2, tm.getNetworkCountryIso());
}
else*/
else
return PhoneNumberUtils.compare(number1, number2);
}
@@ -1893,4 +1911,9 @@ public class Miscellaneous extends Service
return null;
}
public static int getTargetSDK(Context context)
{
return context.getApplicationContext().getApplicationInfo().targetSdkVersion;
}
}

View File

@@ -18,6 +18,7 @@ import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.SubSystemStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
import com.jens.automation2.receivers.TimeZoneListener;
@@ -182,6 +183,9 @@ public class ReceiverCoordinator
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering))
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.subSystemState))
SubSystemStateReceiver.getInstance().startListener(AutomationService.getInstance());
try
{
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
@@ -223,6 +227,7 @@ public class ReceiverCoordinator
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance());
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
SubSystemStateReceiver.getInstance().stopListener(AutomationService.getInstance());
try
{
@@ -440,6 +445,24 @@ public class ReceiverCoordinator
}
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.subSystemState))
{
if(!SubSystemStateReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "SubSystemStateReceiver", "Starting SubSystemStateReceiver because used in a new/changed rule.", 4);
// if(DevicePositionListener.getInstance().haveAllPermission())
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
}
}
else
{
if(SubSystemStateReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "SubSystemStateReceiver", "Shutting down SubSystemStateReceiver because not used in any rule.", 4);
SubSystemStateReceiver.getInstance().stopListener(AutomationService.getInstance());
}
}
AutomationService.updateNotification();
}
}

View File

@@ -60,6 +60,7 @@ public class Trigger
serviceStarts,
broadcastReceived,
tethering,
subSystemState,
phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
@@ -116,12 +117,16 @@ public class Trigger
return context.getResources().getString(R.string.broadcastReceivedTitle);
case tethering:
return context.getResources().getString(R.string.tetheringState);
case subSystemState:
return context.getResources().getString(R.string.subSystemState);
default:
return "Unknown";
}
}
};
public static enum subSystemStates { wifi, bluetooth };
Rule parentRule = null;
Calendar lastTimeNotApplied = null;
@@ -235,6 +240,10 @@ public class Trigger
if(!checkTetheringActive())
result = false;
break;
case subSystemState:
if(!checkSubSystemState())
result = false;
break;
default:
break;
}
@@ -402,12 +411,17 @@ public class Trigger
boolean checkDeviceStarts()
{
return checkServiceStarts() && !Settings.deviceStartDone;
if(triggerParameter && checkServiceStarts() && !Settings.deviceStartDone)
return true;
else if(!triggerParameter && !checkServiceStarts() && Settings.deviceStartDone)
return true;
else
return false;
}
boolean checkServiceStarts()
{
return !Settings.serviceStartDone;
return !Settings.serviceStartDone == getTriggerParameter();
}
boolean checkProfileActive()
@@ -535,6 +549,31 @@ public class Trigger
return true;
}
boolean checkSubSystemState()
{
try
{
subSystemStates state = subSystemStates.valueOf(triggerParameter2);
switch (state)
{
case wifi:
return WifiBroadcastReceiver.isWifiEnabled(Miscellaneous.getAnyContext()) == triggerParameter;
case bluetooth:
return BluetoothReceiver.isBluetoothEnabled() == triggerParameter;
default:
Miscellaneous.logEvent("w", "checkSubSystemState()", "Invalid subSystemState: " + state.name(), 3);
return false;
}
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "checkSubSystemState()", 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);
@@ -728,7 +767,8 @@ public class Trigger
if(this.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Wifi name specified, checking that.", this.getParentRule().getName()), 4);
if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2()))
if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2()) && !(Miscellaneous.isRegularExpression(this.getTriggerParameter2()) && WifiBroadcastReceiver.getLastWifiSsid().matches(this.getTriggerParameter2())))
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()),this.getParentRule().getName()), 3);
return false;
@@ -794,9 +834,15 @@ public class Trigger
boolean checkBatteryLevel()
{
/*
-1 means value is not known, yet.
*/
if(BatteryReceiver.getBatteryLevel() == -1)
return false;
if(this.getTriggerParameter())
{
if(BatteryReceiver.getBatteryLevel() <= this.getBatteryLevel())
if(BatteryReceiver.getBatteryLevel() < this.getBatteryLevel())
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(this.getBatteryLevel()), this.getParentRule().getName()), 3);
return false;
@@ -804,7 +850,10 @@ public class Trigger
}
else
{
if(this.getBatteryLevel() >= this.getBatteryLevel())
if(BatteryReceiver.getBatteryLevel() < 100 && BatteryReceiver.getBatteryLevel() >= this.getBatteryLevel()
||
BatteryReceiver.getBatteryLevel() > this.getBatteryLevel()
)
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(this.getBatteryLevel()), this.getParentRule().getName()), 3);
return false;
@@ -1634,11 +1683,11 @@ public class Trigger
break;
case deviceStarts:
// This type doesn't have an activate/deactivate equivalent
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.deviceHasJustStarted));
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.deviceIsStarting) + ": " + String.valueOf(triggerParameter));
break;
case serviceStarts:
// This type doesn't have an activate/deactivate equivalent
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.serviceHasJustStarted));
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.serviceIsStarting) + ": " + String.valueOf(triggerParameter));
break;
case broadcastReceived:
if(triggerParameter)
@@ -1654,6 +1703,25 @@ public class Trigger
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringNotActive));
break;
case subSystemState:
Trigger.subSystemStates desiredState = subSystemStates.valueOf(triggerParameter2);
switch(desiredState)
{
case wifi:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.wifi));
break;
case bluetooth:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetooth));
break;
}
returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.is) + " ");
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.activated));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.deactivated));
break;
default:
returnString.append("error");
break;

View File

@@ -63,7 +63,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
// int state = -1;
NetworkInfo myWifi = null;
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) //gefeuert bei Trennung
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) // fired upon disconnection
{
// state = intent.getIntExtra(WifiManager.NETWORK_STATE_CHANGED_ACTION, -1);
// Miscellaneous.logEvent("i", "WifiReceiver", "NETWORK_STATE_CHANGED_ACTION: " + String.valueOf(state));

View File

@@ -300,4 +300,16 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
{
return new Trigger_Enum[] { Trigger_Enum.bluetoothConnection };
}
}
/**
* Check for Bluetooth.
*
* @return true if Bluetooth is available.
*/
public static boolean isBluetoothEnabled()
{
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
return bluetoothAdapter != null && bluetoothAdapter.isEnabled() && bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON;
}
}

View File

@@ -2,6 +2,7 @@ package com.jens.automation2.receivers;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.IntentFilter;
import android.os.Build;
@@ -149,51 +150,6 @@ public class NotificationListener extends NotificationListenerService// implemen
return returnNotification;
}
/*@Override
public void startListener(AutomationService automationService)
{
if(instance == null)
instance = new NotificationListener();
if(notificationReceiverIntentFilter == null)
{
notificationReceiverIntentFilter = new IntentFilter();
notificationReceiverIntentFilter.addAction("android.service.notification.NotificationListenerService");
}
try
{
if(!listenerRunning)
{
Miscellaneous.logEvent("i", "NotificationListener", "Starting NotificationListener", 4);
listenerRunning = true;
AutomationService.getInstance().registerReceiver(instance, notificationReceiverIntentFilter);
}
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "BluetoothReceiver", "Error starting BluetoothReceiver: " + Log.getStackTraceString(ex), 3);
}
}
@Override
public void stopListener(AutomationService automationService)
{
}
@Override
public boolean isListenerRunning()
{
return false;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[0];
}*/
public static class SimpleNotification
{
boolean created;
@@ -283,4 +239,35 @@ public class NotificationListener extends NotificationListenerService// implemen
cancelNotification(sbn.getKey());
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void clickNotificationButton(StatusBarNotification sbn, String buttonText)
{
boolean buttonFound = false;
if(sbn.getNotification().actions != null)
{
for (Notification.Action a : sbn.getNotification().actions)
{
if((Miscellaneous.isRegularExpression(buttonText) && a.title.toString().matches(buttonText)) || a.title.toString().equalsIgnoreCase(buttonText))
{
if (!buttonFound)
buttonFound = true;
try
{
Miscellaneous.logEvent("w", "clickNotificationButton()", "Pressing button with text \"" + a.title.toString() + "\".", 2);
a.actionIntent.send();
}
catch (PendingIntent.CanceledException e)
{
Miscellaneous.logEvent("w", "clickNotificationButton()", Log.getStackTraceString(e), 2);
}
}
}
}
if(!buttonFound)
Miscellaneous.logEvent("w", "clickNotificationButton()", "Button with text \n" + buttonText + "\n could not found.", 2);
}
}

View File

@@ -22,8 +22,6 @@ import java.util.ArrayList;
public class PhoneStatusListener implements AutomationListenerInterface
{
// protected static int currentStateIncoming = -1;
// protected static int currentStateOutgoing = -1;
protected static String lastPhoneNumber="";
protected static int lastPhoneDirection = -1; //0=incoming, 1=outgoing
protected static int currentState = -1;
@@ -120,8 +118,6 @@ public class PhoneStatusListener implements AutomationListenerInterface
}
else
{
// state != TelephonyManager.CALL_STATE_IDLE &&
setCurrentState(state);
setLastPhoneDirection(1);
@@ -175,12 +171,12 @@ public class PhoneStatusListener implements AutomationListenerInterface
Miscellaneous.logEvent("i", "Call state", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.outgoingCallTo), getLastPhoneNumber()), 4);
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.phoneCall);
for(int i=0; i<ruleCandidates.size(); i++)
for(int i = 0; i < ruleCandidates.size(); i++)
{
AutomationService asInstance = AutomationService.getInstance();
if(asInstance != null)
if(ruleCandidates.get(i).getsGreenLight(asInstance))
ruleCandidates.get(i).activate(asInstance, false);
ruleCandidates.get(i).activate(asInstance, false);
}
}
}
@@ -289,4 +285,4 @@ public class PhoneStatusListener implements AutomationListenerInterface
{
return new Trigger_Enum[] { Trigger_Enum.phoneCall };
}
}
}

View File

@@ -0,0 +1,151 @@
package com.jens.automation2.receivers;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class SubSystemStateReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
public static AutomationService automationServiceRef = null;
private static IntentFilter subSystemStateIntentFilter = null;
private static BroadcastReceiver subSystemStateReceiverInstance = null;
private static Intent subSystemStatusIntent = null;
private static boolean subSystemStateReceiverActive = false;
static SubSystemStateReceiver instance;
final static String stateBluetooth = "android.bluetooth.adapter.action.STATE_CHANGED";
final static String stateWifi = "android.net.wifi.STATE_CHANGE";
final static String connectivityBroadcast = "android.net.conn.CONNECTIVITY_CHANGE";
static Map<String, Boolean> stateMap = null;
@Override
public void onReceive(Context context, Intent intent)
{
if (intent == null)
return;
if (context == null)
return;
Miscellaneous.logEvent("e", "ScreenStateReceiver", "Received: " + intent.getAction(), 3);
if(stateMap == null)
stateMap = new HashMap<>();
try
{
/*if (intent.getAction().equals(stateWifi) || intent.getAction().equals(connectivityBroadcast))
{
if(intent.hasExtra(WifiManager.EXTRA_WIFI_STATE))
{
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
if (wifiState == WifiManager.WIFI_STATE_ENABLED)
stateMap.put("wifi", true);
else if (wifiState == WifiManager.WIFI_STATE_DISABLED)
stateMap.put("wifi", false);
}
}
else if (intent.getAction().equals(stateBluetooth))
{
if(intent.hasExtra(BluetoothAdapter.EXTRA_STATE))
{
int bluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (bluetoothState == BluetoothAdapter.STATE_ON)
stateMap.put("bluetooth", true);
else if (bluetoothState == BluetoothAdapter.STATE_OFF)
stateMap.put("bluetooth", false);
}
}*/
if (intent.getAction().equals(stateWifi) || intent.getAction().equals(connectivityBroadcast) || intent.getAction().equals(stateBluetooth))
{
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.subSystemState);
for (int i = 0; i < ruleCandidates.size(); i++)
{
if (ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
else
{
Miscellaneous.logEvent("e", "SubSystemStateReceiver", "Unknown state received: " + intent.getAction(), 3);
}
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "SubSystemStateReceiver", "Error receiving screen state: " + e.getMessage(), 3);
}
}
public static SubSystemStateReceiver getInstance()
{
if(instance == null)
instance = new SubSystemStateReceiver();
return instance;
}
@Override
public void startListener(AutomationService automationService)
{
if (!subSystemStateReceiverActive)
{
automationServiceRef = automationService;
if (subSystemStateReceiverInstance == null)
subSystemStateReceiverInstance = new SubSystemStateReceiver();
if (subSystemStateIntentFilter == null)
{
subSystemStateIntentFilter = new IntentFilter();
subSystemStateIntentFilter.addAction(stateWifi);
subSystemStateIntentFilter.addAction(connectivityBroadcast);
subSystemStateIntentFilter.addAction(stateBluetooth);
}
subSystemStatusIntent = automationServiceRef.registerReceiver(subSystemStateReceiverInstance, subSystemStateIntentFilter);
subSystemStateReceiverActive = true;
}
}
@Override
public void stopListener(AutomationService automationService)
{
if (subSystemStateReceiverActive)
{
if (subSystemStateReceiverInstance != null)
{
automationServiceRef.unregisterReceiver(subSystemStateReceiverInstance);
subSystemStateReceiverInstance = null;
}
subSystemStateReceiverActive = false;
}
}
@Override
public boolean isListenerRunning()
{
return subSystemStateReceiverActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[]{Trigger.Trigger_Enum.subSystemState};
}
}

View File

@@ -0,0 +1,31 @@
package com.jens.automation2.ui.main;
import androidx.arch.core.util.Function;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel;
public class PageViewModel extends ViewModel
{
private MutableLiveData<Integer> mIndex = new MutableLiveData<>();
private LiveData<String> mText = Transformations.map(mIndex, new Function<Integer, String>()
{
@Override
public String apply(Integer input)
{
return "Hello world from section: " + input;
}
});
public void setIndex(int index)
{
mIndex.setValue(index);
}
public LiveData<String> getText()
{
return mText;
}
}

View File

@@ -0,0 +1,78 @@
package com.jens.automation2.ui.main;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.jens.automation2.R;
import com.jens.automation2.databinding.FragmentMainActivityTabsBinding;
/**
* A placeholder fragment containing a simple view.
*/
public class PlaceholderFragment extends Fragment
{
private static final String ARG_SECTION_NUMBER = "section_number";
private PageViewModel pageViewModel;
private FragmentMainActivityTabsBinding binding;
public static PlaceholderFragment newInstance(int index)
{
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
pageViewModel = new ViewModelProvider(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null)
{
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
binding = FragmentMainActivityTabsBinding.inflate(inflater, container, false);
View root = binding.getRoot();
final TextView textView = binding.sectionLabel;
pageViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>()
{
@Override
public void onChanged(@Nullable String s)
{
textView.setText(s);
}
});
return root;
}
@Override
public void onDestroyView()
{
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,51 @@
package com.jens.automation2.ui.main;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.jens.automation2.R;
/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter
{
@StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm)
{
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position)
{
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
@Nullable
@Override
public CharSequence getPageTitle(int position)
{
return mContext.getResources().getString(TAB_TITLES[position]);
}
@Override
public int getCount()
{
// Show 2 total pages.
return 2;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 679 B

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -100,6 +100,7 @@
android:id="@+id/bSendEmailToDev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/sendEmailToDev" />
<TextView

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivityTabs">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="@dimen/appbar_padding"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -76,6 +76,14 @@
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/regularExpressionsIfEquals"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
@@ -111,6 +119,22 @@
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/regularExpressionsIfEquals"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
@@ -141,6 +165,69 @@
</TableRow>>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TableRow>
<RadioGroup>
<RadioButton
android:id="@+id/rbNotificationDismissSimple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/simplyDismissNotification" />
<RadioButton
android:id="@+id/rbNotificationDismissButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clickNotificationButton" />
</RadioGroup>
<EditText
android:layout_gravity="bottom"
android:id="@+id/etNotificationDismissalButtonText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:inputType="text" />
</TableRow>
<TableRow>
<TextView />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
</TableRow>
<TableRow>
<TextView />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/mayUseRegularExpressions"
android:layout_marginBottom="@dimen/default_margin"/>
</TableRow>
</TableLayout>
<Button

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">
<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/keepDeviceAwake" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/direction" />
<RadioGroup>
<RadioButton
android:id="@+id/rbWakeLockActivate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/activate" />
<RadioButton
android:id="@+id/rbWakeLockDeactivate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/deactivate" />
</RadioGroup>
</TableRow>
<TableRow>
<TextView
android:text="@string/wakeLockExplanation"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_span="2"
android:layout_marginVertical="@dimen/default_margin" />
</TableRow>
<TableRow>
<TextView
android:text="@string/wakeLockTimeout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/chkWakeLockTimeout"
android:text=""
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/duration" />
<EditText
android:id="@+id/etWakeLockDuration"
android:inputType="number"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</TableRow>
</TableLayout>
<Button
android:id="@+id/bSaveWakelock"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>

View File

@@ -96,6 +96,7 @@
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
@@ -104,6 +105,14 @@
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/regularExpressionsIfEquals"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">

View File

@@ -0,0 +1,75 @@
<?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: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/subSystemState" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rbSubSystemStateWifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/wifi" />
<RadioButton
android:id="@+id/rbSubSystemStateBluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bluetooth" />
</RadioGroup>
<ImageView
android:layout_width="match_parent"
android:layout_span="2"
android:layout_height="1dp"
android:layout_margin="10dp"
android:background="#aa000000" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rbSubSystemStateEnabled"
android:checked="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/activated" />
<RadioButton
android:id="@+id/rbSubSystemStateDisabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/deactivated" />
</RadioGroup>
<Button
android:id="@+id/bSubSystemStateSave"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@@ -58,6 +58,58 @@
</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/rbTetheringTypeAny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/any" />
<RadioButton
android:id="@+id/rbTetheringTypeWifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/wifi" />
<RadioButton
android:id="@+id/rbTetheringTypeBluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bluetooth" />
<RadioButton
android:id="@+id/rbTetheringTypeUsb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/usb" />
<RadioButton
android:id="@+id/rbTetheringTypeCable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cable" />
</RadioGroup>
</TableRow>
</TableLayout>
<Button

View File

@@ -47,6 +47,19 @@
</TableRow>
<TableRow>
<TextView
android:id="@+id/tvWifiTriggerNameLocationNotice"
android:layout_span="2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="@color/red"
android:text="@string/locationRequiredToDetermineWifiName"
android:layout_marginVertical="@dimen/default_margin"
android:visibility="gone" />
</TableRow>
<TableRow>
<TextView
@@ -62,6 +75,16 @@
</TableRow>
<TableRow>
<TextView />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/mayUseRegularExpressions"/>
</TableRow>
<TableRow>
<Button
@@ -81,7 +104,7 @@
</TableLayout>
<Button
android:id="@+id/btriggerWifiSave"
android:id="@+id/bTriggerWifiSave"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.PlaceholderFragment">
<TextView
android:id="@+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_marginBottom="@dimen/activity_vertical_margin"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/constraintLayout"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -519,7 +519,7 @@
<string name="notification">Benachrichtigung</string>
<string name="title">Titel</string>
<string name="text">Text</string>
<string name="anyApp">Irgendeine Anwendung</string>
<string name="anyApp">irgendeine Anwendung</string>
<string name="postsNotification">%1$s zeigt eine Benachrichtung an</string>
<string name="removedNotification">Benachrichtigung von %1$s wurde entfernt</string>
<string name="notificationAppears">Benachrichtigung wird angezeigt</string>
@@ -688,7 +688,7 @@
<string name="screenIs">Bildschirm ist %1$s</string>
<string name="sendEmailToDev">Email an Entwickler schicken</string>
<string name="controlCenter">Steuerungszentrale</string>
<string name="emailContactNotice">Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.</string>
<string name="emailContactNotice">Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.\nViele Fragen können nicht einfach gleich beantwortet werden, sondern erfordern eine technische Prüfung. Haben Sie also bitte etwas Geduld.</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Aufgrund Google\'s unendlicher Weisheit, ist die letzte Android Version, mit der diese Funktion noch funktioniert, die Version %1$s. Sie können es hier einrichten, aber vermutlich wird es keine Auswirkung haben.</string>
<string name="musicPlaying">Musik läuft</string>
<string name="selectParameters">Wählen Sie die Parameter</string>
@@ -706,8 +706,8 @@
<string name="startActivityInsertManually">Diese Einschränkung betrifft nur die Auswahl einer App, nicht den eigentlichen Start. So können Sie den Namen einer Anwendung immer noch manuell eingeben, falls Sie ihn kennen.</string>
<string name="serviceStarts">Dienst startet</string>
<string name="deviceStarts">Gerät startet</string>
<string name="deviceHasJustStarted">Gerät ist gerade gestartet</string>
<string name="serviceHasJustStarted">Dienst ist gerade gestartet</string>
<string name="deviceIsStarting">Gerät startet gerade</string>
<string name="serviceIsStarting">Dienst startet gerade</string>
<string name="broadcastReceived">Broadcast empfangen</string>
<string name="broadcastNotReceived">Broadcast nicht empfangen</string>
<string name="broadcastReceivedTitle">Broadcast empfangen</string>
@@ -737,4 +737,17 @@
<string name="wifiExplanation2">Während der Flugmodus aktiv ist, kann WLAN nur von Anwendungen ein- oder ausgeschaltet werden, wenn root-Rechte dafür verwendet werden.</string>
<string name="wifiExplanation1">Anwendungen, die auf Android Q oder höher ausgerichtet sind, können WLAN nicht mehr ein- oder ausschalten. Daran ist Google schuld, nicht ich.\n\nSie können diese Einschränkung umgehen, indem Sie Ihr Gerät rooten und die Checkbox unten aktivieren. Alternativ laden Sie sich diese Anwendung von F-Droid oder meiner Webseite herunter. In diesen Versionen bin ich nicht gezwungen, die Anwendungen auf die neuesten API Level zu unterstützen.</string>
<string name="runExecutableExplanation">Sie können ein Script oder eine andere ausführbare Datei auswählen, die dann als Aktion ausgeführt wird.\n\nAllerdings gibt es ein paar Voraussetzungen, um die Sie sich selbst kümmern müssen. Google hat es sehr schwer gemacht, irgendetwas außer normalen Android Anwendungen auszuführen.\n\n1.\nDie Datei muß im Dateisystem als ausführbar markiert sein. Auf einem normalen Android-System (ohne Root) ist das in der Tat der schwierigste Teil.\n\n2.\nDas bedeutet auch, daß auch Automation in der Lage sein muß, die Datei auszuführen, nicht nur der Besitzer oder die Gruppe.\n\n3.\nWenn es ein Script ist, muß eine gültige Shell im Header des Scripts definiert sein.</string>
<string name="regularExpressionsIfEquals">Falls \"ist gleich\" ausgewählt ist, können Sie reguläre Ausdrücke eingeben.</string>
<string name="enter_a_number">Geben Sie eine Zahl ein.</string>
<string name="duration">Dauer [ms]</string>
<string name="keepDeviceAwake">Gerät wach halten</string>
<string name="wakeLockTimeout">Zeitlimit angeben</string>
<string name="wakeLockExplanation">Aktivieren wird den Bildschirm anbehalten, während deaktivieren dem Bildschirm erlaubt, auszugehen. Um ihn anzubehalten, können Sie entweder eine Dauer angeben, nach der er ausgehen darf, oder Sie können Sie unendlich lange anlassen. Im letzteren Fall müßten Sie eine neue Gerät wach halten-Aktion definieren, in der Sie \"deaktivieren\" auswählen.</string>
<string name="mayUseRegularExpressions">Sie können hier auch einen regulären Ausdruck eingeben.</string>
<string name="locationRequiredToDetermineWifiName">Um die SSID auslesen zu können, benötigt die Anwendung das Recht Ihren Standort zu erkennen. Weil die Google-Version das nicht kann, können Sie in diesem Auslöser keine SSID spezifizieren. Sie können ihn nur wenden, um zu erkennen, ob WLAN verbunden ist oder nicht.</string>
<string name="withButton">mit der Schaltfläche %1$s</string>
<string name="bluetooth">Bluetooth</string>
<string name="subSystemState">Subsystem Status</string>
<string name="clickNotificationButton">Eine Schaltfläche klicken</string>
<string name="simplyDismissNotification">Regulär schließen</string>
</resources>

View File

@@ -117,7 +117,7 @@
<string name="actionSetUsbTethering">Enrutador USB</string>
<string name="actionTurnBluetoothOn">encender Bluetooth</string>
<string name="actionTurnWifiOn">encender wifi</string>
<string name="actionTurnWifiOff">desactivar Bluetooth</string>
<string name="actionTurnWifiOff">desactivar wifi</string>
<string name="actionTurnBluetoothOff">desactivar Bluetooth</string>
<string name="actionTriggerUrl">Abrir URL en antecedentes</string>
<string name="actionChangeSoundProfile">Cambiar perfil sonido</string>
@@ -687,7 +687,7 @@
<string name="screenIs">pantalla esta %1$s</string>
<string name="sendEmailToDev">Enviar email al desrollador</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Debido a la infinita sabiduría de Google, la última versión de Android en la que se sabe que funciona esta función es %1$s. Puede configurarlo, pero probablemente no tendrá ningún efecto.</string>
<string name="emailContactNotice">El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.</string>
<string name="emailContactNotice">El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.\nMuchas preguntas no se pueden responder de inmediato, pero requieren cierta investigación técnica. Así que, por favor, tengan un poco de paciencia.</string>
<string name="actionMediaControlNotice">Ten en cuenta que esta acción puede no funcionar con TODOS los jugadores. E incluso si lo hace, no todos los botones funcionan necesariamente.</string>
<string name="musicPlaying">Musica esta reproduciendo</string>
<string name="selectParameters">Elije parametros</string>
@@ -705,8 +705,8 @@
<string name="startActivityInsertManually">Esta limitación se refiere solo a la selección de una aplicación, no al inicio real. Por lo tanto, aún puede ingresar el nombre de una aplicación manualmente si lo conoce.</string>
<string name="deviceStarts">Dispositivo esta enciendo</string>
<string name="serviceStarts">Servicio esta enciendo</string>
<string name="deviceHasJustStarted">el dispositivo justamente ha encendido</string>
<string name="serviceHasJustStarted">el servicio justamente ha encendido</string>
<string name="deviceIsStarting">el dispositivo justamente esta encendido</string>
<string name="serviceIsStarting">el servicio justamente esta encendido</string>
<string name="emailPretext">Si tiene un problema, sugerencia o pregunta, escriba algo en el correo electrónico. No solo envíeme los archivos con el cuerpo de correo predeterminado. Ignoraré todo eso a menos que ya estemos en una conversación.</string>
<string name="lockedCommentScreenMustBeOff">Cualquier estado de bloqueo solo se detectará si la pantalla está apagada.</string>
<string name="lockedWithSecurity">bloqueado (con PIN, etc.)</string>
@@ -722,4 +722,31 @@
<string name="explanationBroadcastTrigger">La mayoría de los eventos en su teléfono se \"publicado\" transmitiéndolos a través del sistema operativo.\nPor ejemplo, activar / desactivar el modo avión activará dicha transmisión. Esas transmisiones no son automáticamente visibles / audibles, pero si una aplicación (como Automatización) está interesada, puede conectarse a ellas. Cuando ocurran, se le notificará y podrá reaccionar.\n\nPuede definir aquí un evento de difusión para el que la aplicación esperará. Puede ingresarlo manualmente, copiarlo y pegarlo desde algún lugar o elegir uno de la lista de sugerencias. Como este desencadenante está destinado a ser y seguir siendo muy flexible, no puedo proporcionarle explicaciones para los elementos.\n\nLa lista de sugerencias no pretende estar completa. Visite la siguiente URL para echar un vistazo a la documentación de Android.\nTambién cualquier aplicación puede enviar eventos personalizados que no aparecerán en la documentación de Android, por supuesto.\n\nMuchas transmisiones requieren permisos específicos para funcionar. Intento solicitar permisos donde sé que serán necesarios. Si cree que se requiere un permiso para la acción que ingresó, hágamelo saber.\n\nNo recibido significa que no ha habido tal transmisión desde que se inició el servicio. Responder a ciertos parámetros está en desarrollo.</string>
<string name="logsExplanation">Para evitar el uso innecesario del almacenamiento, los registros no se guardan de forma predeterminada. Entonces, si tiene un problema, active primero la configuración de inicio de sesión y establezca el nivel de registro en 5. A continuación, reproduzca el problema. Solo entonces se pueden adjuntar registros.</string>
<string name="directionStringDoesNotContain">no contiene</string>
<string name="enter_a_number">Introduzca un número.</string>
<string name="regularExpressionsIfEquals">Si se selecciona \"igual\", puede introducir una expresión regular.</string>
<string name="duration">Duración [ms]</string>
<string name="keepDeviceAwake">Mantenga el dispositivo despierto</string>
<string name="wakeLockTimeout">Especificar el tiempo de espera</string>
<string name="runAsRoot">Ejecutar con root</string>
<string name="path">Ruta de acceso</string>
<string name="runExecutable">Ejecutar script o ejecutable</string>
<string name="parameters">Parámetros</string>
<string name="chooseExecutable">Elegir ejecutable</string>
<string name="selectValidExecutable">Elija valido archivo ejecutable.</string>
<string name="fileNotExecutable">Este archivo no es ejecutable.</string>
<string name="usingRoot">con root</string>
<string name="tetheringActive">tethering esta activo</string>
<string name="tetheringNotActive">tethering no esta activo</string>
<string name="tetheringState">Estado de tethering</string>
<string name="wifiExplanation2">Mientras modo vuelo esta activo, solo aplicaciones que tienen el permiso root pueden encender/desactivar wifi.</string>
<string name="wifiExplanation1">Las aplicaciones dirigidas a Android Q o superior ya no pueden activar o desactivar el wifi. Por favor, culpe a Google por esta restricción, no a mí. Puede omitir esta restricción rooteando su dispositivo y activando la casilla de verificación a continuación. Alternativamente, descargue esta aplicación de F-Droid o mi sitio web, ya que no estoy obligado a apuntar al último nivel de API en esas versiones.</string>
<string name="runExecutableExplanation">Puede seleccionar un script o un archivo ejecutable aquí que se ejecutará como una acción. Pero hay algunos requisitos previos con los que tienes que lidiar por tu cuenta. Google ha hecho que sea muy difícil ejecutar cualquier otra cosa que no sean aplicaciones normales de Android. 1. El archivo debe estar marcado como ejecutable en el sistema de archivos. En un sistema Android normal (sin root) esta es en realidad la parte difícil. 2. Eso también significa que la automatización debe poder ejecutar el archivo, no solo el propietario o el grupo. 3. Si se trata de un script, se especificará un shell válido en el encabezado del script.</string>
<string name="wakeLockExplanation">Activar mantendrá la pantalla encendida mientras desactiva la dejará apagarla. Para mantenerlo encendido, puede ingresar una duración después de la cual puede apagarse nuevamente o puede mantenerlo encendido indefinidamente. En este último caso, deberá crear otra acción de mantenerse despierto (en esta u otra regla) en la que seleccione desactivar.</string>
<string name="mayUseRegularExpressions">Aqui tambien puede insertar expressiones regulares.</string>
<string name="locationRequiredToDetermineWifiName">Para obtener el SSID wifi, la aplicación requiere permisos de ubicación. Debido a que la versión de Google no puede obtener eso, solo puede usar este desencadenador si no especifica un SSID. Por lo tanto, solo se puede usar para detectar si wifi está conectado o no.</string>
<string name="withButton">con botón %1$s</string>
<string name="bluetooth">Bluetooth</string>
<string name="subSystemState">Estado del subsystema</string>
<string name="clickNotificationButton">Cliquar un botón</string>
<string name="simplyDismissNotification">Simplemente desestimar</string>
</resources>

View File

@@ -90,7 +90,7 @@
<string name="anotherProfileByThatName">Nome già usato per un altro profilo.</string>
<string name="anotherRuleByThatName">Nome già usato per un\'altra regola.</string>
<string name="any">qualsiasi</string>
<string name="anyApp">Qualsiasi applicazione</string>
<string name="anyApp">qualsiasi applicazione</string>
<string name="anyDevice">qualsiasi dispositivo</string>
<string name="anyLocation">qualsiasi posizione</string>
<string name="anyNumber">qualsiasi numero</string>
@@ -689,7 +689,7 @@
<string name="screenIs">lo schermo è %1$s</string>
<string name="sendEmailToDev">Invia email allo sviluppatore</string>
<string name="controlCenter">Centro di controllo</string>
<string name="emailContactNotice">L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.</string>
<string name="emailContactNotice">L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.\nMolte domande non possono essere risolte immediatamente, ma richiedono alcune ricerche tecniche. Quindi, per favore, abbiate un po\' di pazienza.</string>
<string name="musicPlaying">La musica è in riproduzione</string>
<string name="musicIsPlaying">la musica è in riproduzione</string>
<string name="musicIsNotPlaying">la musica non viene riprodotta</string>
@@ -706,8 +706,8 @@
<string name="startActivityInsertManually">Questa limitazione riguarda solo la selezione di un\'app, non l\'avvio effettivo. Quindi puoi comunque inserire manualmente il nome di un\'applicazione se lo conosci.</string>
<string name="deviceStarts">Device starts</string>
<string name="serviceStarts">Avvio del servizio</string>
<string name="deviceHasJustStarted">il dispositivo è appena stato avviato</string>
<string name="serviceHasJustStarted">il servizio è appena stato avviato</string>
<string name="deviceIsStarting">Il dispositivo si sta avviando</string>
<string name="serviceIsStarting">il servizio è in fase di avvio</string>
<string name="broadcastReceived">broadcast ricevuto</string>
<string name="broadcastNotReceived">broadcast non ricevuto</string>
<string name="broadcastReceivedTitle">Broadcast ricevuto</string>
@@ -737,4 +737,17 @@
<string name="wifiExplanation2">Quando la modalità aereo è attiva, lo stato del wifi può essere commutato soltanto da applicazioni che usano i permessi di root.</string>
<string name="wifiExplanation1">Le app che hanno come target Android Q o superiore non possono più attivare o disattivare il wifi. Lamentatevi con Google per questa limitazione, non con me.\n\nSi può aggirare questa limitazione usando il root e spuntando la casella qua sotto. In alternativa si può scaricare questa applicazione da F-Droid o dal mio sito, dove non sono obbligato a usare come target le ultime API.</string>
<string name="runExecutableExplanation">"Si può scegliere uno script o un eseguibile che sarà eseguito come azione.\n\nCi sono però dei prerequisiti che devi sistemare per conto tuo. Google ha reso molto difficile eseguire tutto tranne le normali applicazioni Android.\n\n1.\nIl file deve essere eseguibile nel file system. In un sistema Android normale (senza root) questa è la parte più difficile.\n\n2.\nAnche Automation deve poter eseguire il file, non soltanto il proprietario o il gruppo.\n\n3.\nSe si tratta di uno script, deve essere specificata una shell valida nell'intestazione. "</string>
<string name="enter_a_number">Inserisci un numero.</string>
<string name="regularExpressionsIfEquals">Se è selezionato \"uguale\", è possibile immettere un\'espressione regolare.</string>
<string name="duration">Durata [ms]</string>
<string name="keepDeviceAwake">Mantieni il dispositivo attivo</string>
<string name="wakeLockTimeout">Specificare il timeout</string>
<string name="wakeLockExplanation">Attiva manterrà lo schermo acceso mentre disattivato lo lascerà spegnere. Per tenerlo acceso puoi inserire una durata dopo la quale potrebbe spegnersi di nuovo o puoi tenerlo acceso a tempo indeterminato. In quest\'ultimo caso è necessario creare un\'altra azione keep-awake (in questa o in un\'altra regola) in cui selezionare disattiva.</string>
<string name="mayUseRegularExpressions">Puoi anche inserire un\'espressione regolare qui.</string>
<string name="locationRequiredToDetermineWifiName">Per ottenere l\'SSID wifi, l\'app richiede autorizzazioni di posizione. Poiché la versione di Google non è in grado di ottenerlo, è possibile utilizzare questo trigger solo se non si specifica un SSID. Quindi può essere utilizzato solo per rilevare se il wifi è connesso o meno.</string>
<string name="simplyDismissNotification">Semplicemente licenziare</string>
<string name="clickNotificationButton">Fai clic su un pulsante</string>
<string name="withButton">con pulsante %1$s</string>
<string name="subSystemState">Stato del sottosistema</string>
<string name="bluetooth">Bluetooth</string>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>

View File

@@ -516,7 +516,7 @@
<string name="directionStringStartsWith">begint met</string>
<string name="directionStringEndsWith">eindigt met</string>
<string name="directionStringNotEquals">is niet gelijk aan</string>
<string name="anyApp">Elke app</string>
<string name="anyApp">elke app</string>
<string name="notificationTriggerExplanation">Deze trigger zal reageren op andere applicaties die meldingen openen in het meldingsgebied (of die worden gesloten). Je kunt een andere applicatie specificeren waar de melding vandaan moet komen. Als je dat niet doet, tellen de meldingen van een andere toepassing mee. U kunt ook tekenreeksen opgeven die wel of niet in de titel of de body van de melding moeten voorkomen. De vergelijking gebeurt hoofdletter-IN-sensitief.</string>
<string name="postsNotification">%1$s berichten notificatie</string>
<string name="removedNotification">kennisgeving van %1$s verwijderd</string>
@@ -667,7 +667,7 @@
<string name="comparisonCaseInsensitive">Vergelijkingen worden gedaan case-INsensitief</string>
<string name="profileWarning">De instellingen die je hier maakt kunnen ervoor zorgen dat je bepaalde dingen niet meer van je telefoon merkt. Ze kunnen zelfs je wekker dempen. Dus wat je ook doet - het wordt aanbevolen om het te testen - ook na Android upgrades.</string>
<string name="ifString">als</string>
<string name="emailContactNotice">E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.</string>
<string name="emailContactNotice">E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.\nVeel vragen kunnen niet meteen worden beantwoord, maar vereisen wel wat technisch onderzoek. Dus heb alsjeblieft wat geduld.</string>
<string name="controlCenter">Controlecentrum</string>
<string name="sendEmailToDev">Stuur een e-mail naar de ontwikkelaar</string>
<string name="screenIs">scherm is %1$s</string>
@@ -702,8 +702,8 @@
<string name="timeFrameDaysHint">Als u een tijdsbestek gebruikt dat zich uitstrekt over middernacht, moet u ook de volgende dag selecteren als u wilt dat de trigger na middernacht van toepassing is.</string>
<string name="featureNotInGooglePlayVersion">Deze functie is niet meer beschikbaar in de Google Play-versie.\\n\\nAlles af en toe pest Google ontwikkelaars. Als u bepaalde functies wilt blijven gebruiken, moet u papierwerk indienen. Helaas is er een kans van 99% dat het papierwerk wordt afgewezen. Het is vrijwel net als in de Asterix-strip / film.\\n\\nIk heb in het verleden wekenlang met hen gediscussieerd over dergelijke gevallen, maar ik bleef afwijzingen krijgen - hetzij door bots of mensen die ongeveer net zo intelligent zijn als bots. In de ik kan kiezen tussen de app die volledig uit de Play Store wordt verwijderd of de functie verwijdert.\\n Overweeg de APK-versie van mijn website of die van F-Droid te gebruiken als je die functies nodig hebt.</string>
<string name="startActivityInsertManually">Deze beperking heeft alleen betrekking op de selectie van een app, niet op de daadwerkelijke start. U kunt dus nog steeds handmatig de naam van een toepassing invoeren als u deze kent.</string>
<string name="deviceHasJustStarted">apparaat is net gestart</string>
<string name="serviceHasJustStarted">service is net begonnen</string>
<string name="deviceIsStarting">apparaat start</string>
<string name="serviceIsStarting">service wordt gestart</string>
<string name="serviceStarts">Service start</string>
<string name="deviceStarts">Apparaat start</string>
<string name="emailPretext">Als je een probleem, suggesties of vraag hebt, schrijf dan iets in de e-mail. Stuur me niet alleen de bestanden met de standaard e-mailtekst. Ik zal alles negeren, tenzij we al in gesprek zijn.</string>
@@ -735,5 +735,18 @@
<string name="tetheringActive">tethering is actief</string>
<string name="tetheringNotActive">tethering is niet actief</string>
<string name="tetheringState">Tethering-status</string>
<string name="enter_a_number">Voer een getal in.</string>
<string name="regularExpressionsIfEquals">Als \'gelijk aan\' is geselecteerd, kunt u een reguliere expressie invoeren.</string>
<string name="duration">Duur [ms]</string>
<string name="keepDeviceAwake">Houd het apparaat wakker</string>
<string name="wakeLockTimeout">Time-out opgeven</string>
<string name="wakeLockExplanation">Activeren houdt het scherm aan terwijl deactiveren het uitschakelt. Om het aan te houden, kunt u een duur invoeren waarna het weer kan worden uitgeschakeld of u kunt het voor onbepaalde tijd aanhouden. In het laatste geval zou je nog een keep-awake actie moeten maken (in deze of een andere regel) waarin je deactiveren selecteert.</string>
<string name="mayUseRegularExpressions">U kunt hier ook een reguliere expressie invoeren.</string>
<string name="locationRequiredToDetermineWifiName">Om de wifi-SSID te krijgen, heeft de app locatiemachtigingen nodig. Omdat de Google-versie dat niet kan krijgen, kun je deze trigger alleen gebruiken als je geen SSID opgeeft. Het kan dus alleen worden gebruikt om te detecteren of wifi is verbonden of niet.</string>
<string name="simplyDismissNotification">Gewoon negeren</string>
<string name="clickNotificationButton">Klik op een knop</string>
<string name="withButton">met knop %1$s</string>
<string name="subSystemState">Status van het subsysteem</string>
<string name="bluetooth">Bluetooth</string>
</resources>

View File

@@ -671,7 +671,6 @@
<string name="from">от</string>
<string name="to">к</string>
<string name="matching">совпадает</string>
<string name="urlRegex" translatable="false">https://regex101.com/</string>
<string name="loadWifiList">Загрузить список Wi-Fi</string>
<string name="needLocationPermForWifiList">Список Wi-Fi, к которому было подключено ваше устройство. Можно использовать для определения того, в каких местах вы были. Вот почему для загрузки списка Wi-Fi требуется разрешение на доступ к местоположению. Если вы хотите выбрать один из из списка, вам необходимо предоставить это разрешение. Если вы этого не хотите, вы все равно можете ввести свое имя Wi-Fi вручную.</string>
<string name="noKnownWifis">На вашем устройстве нет известных Wi-Fi.</string>
@@ -765,7 +764,7 @@
<string name="comparisonCaseInsensitive">Сравнения проводятся без учета регистра</string>
<string name="profileWarning">Настройки, которые вы можете изменить здесь, могут привести к тому, что вы больше не заметите определенных вещей с вашего телефона. Они могут даже отключить будильник. Так что что бы вы ни делали - рекомендуется это проверять.</string>
<string name="ifString">если</string>
<string name="emailContactNotice">Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.</string>
<string name="emailContactNotice">Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.\nМногие вопросы не могут быть решены сразу, но требуют некоторых технических исследований. Поэтому, пожалуйста, наберитесь терпения.</string>
<string name="controlCenter">Центр управления</string>
<string name="sendEmailToDev">Отправить электронное письмо разработчику</string>
<string name="screenIs">экран %1$s</string>
@@ -802,8 +801,8 @@
<string name="startActivityInsertManually">Это ограничение касается только выбора приложения, но не его запуска. Вы можете указать имя приложения вручную, если знаете его.</string>
<string name="deviceStarts">Включение устройства</string>
<string name="serviceStarts">Запуск службы</string>
<string name="deviceHasJustStarted">устроство было включено</string>
<string name="serviceHasJustStarted">служба была запущена</string>
<string name="deviceIsStarting">устройство запускается</string>
<string name="serviceIsStarting">Служба запускается</string>
<string name="broadcastReceived">получено сообщение broadcast</string>
<string name="broadcastNotReceived">сообщение broadcast не получено</string>
<string name="explanationBroadcastTrigger">Большинство событий на вашем телефоне будут \"опубликованы\" при помощи Broadcast сообщений, которые передаются через операционную систему Android.\nНапример, включение/выключение режима "В самолёте" отправит подобное сообщение. Эти сообщения не видны/слышны, но если какое-нибудь приложение (как Automation) могут \"слушать\" их и когда они появляются, реагировать каким-либо образом.\n\nЗдесь вы можете настроить broadcast сообщение, которое Automation будет слушать. Вы можете ввести его вручную, скопировать откуда-нибудь или выбрать из списка. Так как этот триггер является очень гибким, я не могу предоставить вам объяснения по каждому из пунктов списка.\n\nПолнота списка не гарантируется, пожалуйста, перейдите по ссылке ниже для ознакомления с документацией Android.\nДополнительно, любое приложение может отправлять свои собственные сообщения, формат которых в документации Android, конечно же отсутствует.\n\nМногие broadcast сообщения для работы требуют специальных разрешений. Я попытался реализовать запрос разрешений там, где я знаю, что они необходимы. Если вы обнаружите, что где-то не происходит запрос разрешения, где по вашему мнению это нобходимо, пожалуйста сообщите мне.\n\n"Не получено"- значит такое сообщение не было получено с момента старта службы Automation. Реакция на некоторые параметры находится в разработке.</string>
@@ -833,4 +832,17 @@
<string name="tetheringActive">раздача интернета активна</string>
<string name="tetheringNotActive">раздача интернета не активна</string>
<string name="tetheringState">Раздача интернета</string>
<string name="enter_a_number">Введите число.</string>
<string name="regularExpressionsIfEquals">Если выбрано значение \"равно\", можно ввести регулярное выражение.</string>
<string name="duration">продолжительность [мс]</string>
<string name="keepDeviceAwake">Держите устройство в режиме сна</string>
<string name="wakeLockTimeout">указать время ожидания</string>
<string name="wakeLockExplanation">Activate будет держать экран включенным, в то время как деактивация позволит ему выключиться. Для поддержания его включенным вы можете либо ввести продолжительность, после которой он может снова отключиться, либо вы можете держать его включенным на неопределенный срок. В последнем случае вам нужно будет создать еще одно действие keep-awake (в том или ином правиле), в котором вы выберете деактивировать.</string>
<string name="mayUseRegularExpressions">Здесь также можно ввести регулярное выражение.</string>
<string name="locationRequiredToDetermineWifiName">Чтобы получить SSID Wi-Fi, приложению требуются разрешения на местоположение. Поскольку версия Google не может получить его, вы можете использовать этот триггер только в том случае, если вы не указали SSID. Таким образом, его можно использовать только для определения того, подключен ли Wi-Fi или нет.</string>
<string name="withButton">с кнопкой %1$s</string>
<string name="bluetooth">Bluetooth</string>
<string name="subSystemState">Состояние подсистемы</string>
<string name="clickNotificationButton">Нажмите кнопку</string>
<string name="simplyDismissNotification">Просто уволить</string>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">200dp</dimen>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>

View File

@@ -3,4 +3,7 @@
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="default_margin">20dp</dimen>
<dimen name="appbar_padding">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="appbar_padding_top">8dp</dimen>
</resources>

View File

@@ -618,7 +618,7 @@
<string name="directionStringStartsWith">starts with</string>
<string name="directionStringEndsWith">ends with</string>
<string name="directionStringNotEquals">not equals</string>
<string name="anyApp">Any app</string>
<string name="anyApp">any app</string>
<string name="notificationTriggerExplanation">This trigger will respond to other applications opening notifications in the notification area (or such being closed). You can specify another application from which the notification has to come from. If you don\'t the notifications from any other application will count. You can also specify strings that must be or must not be in their title or notification body. The comparison is done case-INsensitive.</string>
<string name="postsNotification">%1$s posts notification</string>
<string name="removedNotification">notification from %1$s removed</string>
@@ -766,7 +766,7 @@
<string name="comparisonCaseInsensitive">Comparisons are done case-INsensitive</string>
<string name="profileWarning">The settings you can adjust here, can cause that you don\'t notice certain things from your phone anymore. They may even silence your wakeup alarm. So whatever you do - it is highly recommended that you test it - also after Android updates.</string>
<string name="ifString">if</string>
<string name="emailContactNotice">Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.</string>
<string name="emailContactNotice">Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.\nMany questions cannot be answered straight away, but require some technical research. So please have some patience.</string>
<string name="controlCenter">Control center</string>
<string name="sendEmailToDev">Send email to developer</string>
<string name="screenIs">screen is %1$s</string>
@@ -802,8 +802,8 @@
<string name="startActivityInsertManually">This limitation concerns only the selection of an app, not the actual start. So you can still enter the name of an application manually if you know it.</string>
<string name="deviceStarts">Device starts</string>
<string name="serviceStarts">Service starts</string>
<string name="deviceHasJustStarted">device has just started</string>
<string name="serviceHasJustStarted">service has just started</string>
<string name="deviceIsStarting">device is starting</string>
<string name="serviceIsStarting">service is starting</string>
<string name="broadcastReceived">broadcast received</string>
<string name="broadcastNotReceived">broadcast not received</string>
<string name="explanationBroadcastTrigger">Most events on your phone will be \"published\" by broadcasting them throughout the operating system.\nFor example turning on/off airplane mode will trigger such a broadcast. Those broadcasts are not automatically visible/audible, but if an application (like Automation) is interested it can hook up to them. When they occur it will get notified and can react.\n\nYou can define a broadcast event here for which the application will wait. You may enter it manually, copy &amp; paste it from somewhere or pick one from the list of suggestions. As this trigger is meant to be and remain very flexible I cannot provide you with explanations for the items.\n\nThe list of suggestions does not claim to be complete. Please visit the below URL to have a look at the Android documentation.\nAlso any app can send custom events which will not appear in the Android documentation of course.\n\nMany broadcasts require specific permissions in order to work. I try to request permissions where I know they will be required. If you think a permission is required for the action you entered, please let me know.\n\nNot received means there has not been such a broadcast ever since the service has been started. Responding to certain parameters is in development.</string>
@@ -815,7 +815,7 @@
<string name="lockedWithoutSecurity">locked (swipe only, no PIN)</string>
<string name="lockedWithSecurity">locked (with PIN, etc.)</string>
<string name="lockedCommentScreenMustBeOff">Any state of locked will only be detected if the screen is off.</string>
<string name="emailPretext">If you have a problem, suggestions or question, please write something in the email. Do not just send me the files with the default mail body. I will ignore everything those unless we\'re already in a conversation.</string>
<string name="emailPretext">If you have a problem, suggestions or question, please write something in the email. Do not just send me the files with the default mail body. I will ignore those unless we\'re already in a conversation.</string>
<string name="sendBroadcast">Send broadcast</string>
<string name="enterBroadcast">Enter a broadcast action.</string>
<string name="broadcastExplanation">This action allows to send a broadcast across the Android OS messaging system. This is not user-visible, but apps who listen for that specific broadcast can respond to it being sent.</string>
@@ -827,11 +827,30 @@
<string name="runAsRoot">Run as root</string>
<string name="selectValidExecutable">Select a valid executable file.</string>
<string name="fileNotExecutable">The file is not executable.</string>
<string name="wifiExplanation1">Apps targeting Android Q or higher cannot turn wifi on or off anymore. Please blame Google for this restriction, not me.\n\nYou can bypass this restriction by rooting your device and activating the checkbox below. Alternatively download this application from F-Droid or my website as I am not forced to target the latest API level in those versions.</string>
<string name="wifiExplanation1">Apps targeting Android Q or higher cannot turn wifi on or off anymore. Please blame Google for this restriction, not me. You can bypass this restriction by rooting your device and activating the checkbox below. Alternatively download this application from F-Droid or my website as I am not forced to target the latest API level in those versions.</string>
<string name="wifiExplanation2">While airplane mode is activated, wifi can only be toggled from applications when using root permissions for that.</string>
<string name="usingRoot">using root</string>
<string name="runExecutableExplanation">You can select a script or an executable file here that will be executed as an action.\n\nBut there are some prerequisites which you have to deal with on your own. Google has made it very hard to run anything other than regular Android applications.\n\n1.\nThe file must be marked as executable in the file system. On a regular Android system (without root) this is actually the hard part.\n\n2.\nThat also means Automation must be able to execute the file, not just the owner or the group.\n\n3.\nIf it is a script, a valid shell be specified in the script\'s header.</string>
<string name="runExecutableExplanation">You can select a script or an executable file here that will be executed as an action. But there are some prerequisites which you have to deal with on your own. Google has made it very hard to run anything other than regular Android applications. 1. The file must be marked as executable in the file system. On a regular Android system (without root) this is actually the hard part. 2. That also means Automation must be able to execute the file, not just the owner or the group. 3. If it is a script, a valid shell be specified in the script\'s header.</string>
<string name="tetheringActive">tethering is active</string>
<string name="tetheringNotActive">tethering is not active</string>
<string name="tetheringState">Tethering state</string>
<string name="regularExpressionsIfEquals">If \"equals\" is selected, you may enter a regular expression.</string>
<string name="enter_a_number">Enter a number.</string>
<string name="duration">Duration [ms]</string>
<string name="keepDeviceAwake">Keep device awake</string>
<string name="wakeLockTimeout">Specify timeout</string>
<string name="wakeLockExplanation">Activate will keep the screen on while deactivate will let it turn off. For keeping it on you can either enter a duration after which it may turn off again or you can keep it on indefinitely. In the latter case you would need to create another keep-awake action (in this or another rule) in which you select deactivate.</string>
<string name="mayUseRegularExpressions">You may also enter a regular expression here.</string>
<string name="simplyDismissNotification">Simply dismiss</string>
<string name="clickNotificationButton">Click a button</string>
<string name="withButton">with button %1$s</string>
<string name="subSystemState">Subsystem state</string>
<string name="bluetooth">Bluetooth</string>
<string name="locationRequiredToDetermineWifiName">To get the wifi SSID, the app requires location permissions. Because the Google version cannot get that, you can only use this trigger if you do not specify an SSID. So it can only be used to detect if wifi is connected or not.</string>
<string name="title_activity_main_tabs">MainActivityTabs</string>
<string name="tab_text_1">Tab 1</string>
<string name="tab_text_2">Tab 2</string>
<string name="usb">USB</string>
<string name="type">Type</string>
<string name="cable">Cable</string>
</resources>

View File

@@ -13,4 +13,13 @@
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View File

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

View File

@@ -54,7 +54,7 @@ Wenn Sie ein Problem mit der Anwendung haben und mich dazu kontaktieren möchten
Spenden sind sicher eine gute, aber nicht die einzige Möglichkeit mich zu motivieren :-)
* Wer mir etwas Gutes tun will, kann die Anwendung auch im Play Store bewerten (https://play.google.com/store/apps/details?id=com.jens.automation2).
* Wenn Ihnen die Anwendung gefällt, freue ich mich auch einfach nur über eine Email mit ein paar netten Worten.
* Außerdem ist immer Hilfe bei der Übersetzung willkommen. Englisch, Spanisch und Deutsch kann ich selbst, Italienisch ist bereits abgedeckt. Aber sonst ist alles gern gesehen.
* Außerdem ist immer Hilfe bei der Übersetzung willkommen. Englisch, Spanisch und Deutsch kann ich selbst, Italienisch und Russisch sind bereits abgedeckt. Aber sonst ist alles gern gesehen.
* Wenn Sie ein Talent/Erfahrung auf dem Gebiet Grafikdesign haben und Ideen für hübschere Symbole haben, lassen Sie es mich wissen.
* Falls Sie einen interessanten Anwendungsfall haben oder einen Weg gefunden haben, Auslöser und Aktionen so zu kombinieren, um etwas Besonderes umzusetzen und Sie denken, daß man das auf die Beispielseite (https://server47.de/automation/examples.html) setzen sollte, kontaktieren Sie mich doch.

View File

@@ -0,0 +1,7 @@
* New action: Keep phone turned on
* New: Regular expressions enabled where comparisons apply (one has to use "equals")
* New: Notification closing can now also be achieved by clicking a button of the target notification.
* Fixed: Changed input type for decimal numbers when adding intent data
* Fixed: Battery level trigger not working when using direction falling-below
* New: Wifi trigger can now use Regex for SSID
* Fixed: Battery receiver would trigger at 100 if specified above 100

View File

@@ -54,7 +54,7 @@ If you have a problem and think about contacting me please
Donations are certainly a good, but not the only way to motivate me :-)
* If you'd like to support me, you can also leave a positive review for the app on Google Play (https://play.google.com/store/apps/details?id=com.jens.automation2).
* If you like the app, simply some warm words via email are always appreciated.
* Furthermore I can always use help in translating the app. English, German and some Spanish are among my own skills. Italian is covered by somebody already. But everything else is more than welcome.
* Furthermore I can always use help in translating the app. English, German and some Spanish are among my own skills. Italiano e russo sono già coperti. But everything else is more than welcome.
* If you have a talent/experience in graphics design and have some ideas for nicer icons let me know.
* If you have an interesting use-case or found a way to combine triggers and actions to achieve something intriguing and you think it's worth putting it on the examples page (https://server47.de/automation/examples.html), let me know.

View File

@@ -54,7 +54,7 @@ Si tiene un problema y considera contactarme
Donaciónes seguramente son una buena, pero no la unica posibilidad de apoyarme :-)
* Si quiere apoyarme puedes escribir un buena revisión en Google Play (https://play.google.com/store/apps/details?id=com.jens.automation2).
* Si le gusta la aplicación, simplemente algunas palabras cálidas por correo electrónico siempre son apreciadas.
* Además siempre necesito ayuda en traduciendo la app. Ingles, Aleman y Español estan en mis habilidades. Todavia tengo ayuda con Italiono. Per todo lo demás es bienvenido.
* Además siempre necesito ayuda en traduciendo la app. Ingles, Aleman y Español estan en mis habilidades. Todavia tengo ayuda con Italiono y Ruso. Per todo lo demás es bienvenido.
* Si tiene talento/experiencia en el campo del diseño gráfico y tienes ideas para crear iconos más bonitos, házmelo saber.
* Si tiene un caso de uso interesante o ha encontrado una forma de combinar condiciones y acciones para lograr algo intrigante y cree que vale la pena ponerlo en la página de ejemplos (https://server47.de/automation/examples.html), házmelo saber.

View File

@@ -57,7 +57,7 @@ Als je een probleem hebt en erover denkt om contact met me op te nemen
Donaties zijn zeker een goede, maar niet de enige manier om mij te motiveren :-)
* Als je me wilt steunen, kun je ook een positieve review voor de app achterlaten op Google Play ( https://play.google.com/store/apps/details?id=com.jens.automation2 ).
* Als de app u bevalt, worden enkele warme woorden via e-mail altijd op prijs gesteld.
* Verder kan ik altijd hulp gebruiken bij het vertalen van de app. Engels, Duits en wat Spaans behoren tot mijn eigen vaardigheden. Italiaans wordt al door iemand gedekt. Maar al het andere is meer dan welkom.
* Verder kan ik altijd hulp gebruiken bij het vertalen van de app. Engels, Duits en wat Spaans behoren tot mijn eigen vaardigheden. Italiaans en Russisch zijn al gedekt. Maar al het andere is meer dan welkom.
* Als je talent/ervaring hebt in grafische vormgeving en ideeën hebt voor mooiere iconen, laat het me weten.
* Als u een interessante use-case heeft of een manier om triggers en acties te combineren om iets intrigerends te bereiken en u denkt dat het de moeite waard is om het op de voorbeelden pagina te zetten (https://server47.de/automation/examples.html), laat het me weten.