Compare commits

..
Author SHA1 Message Date
jens ce32502eaa URL checker 2026-10-01 18:29:17 +02:00
jens 81812eba1b Bug in German translation 2026-09-30 18:22:12 +02:00
9 changed files with 69 additions and 103 deletions
+1 -5
View File
@@ -7,7 +7,7 @@ android {
defaultConfig {
applicationId "com.jens.automation2"
minSdkVersion 24
minSdkVersion 19
compileSdkVersion 37
buildToolsVersion '36.0.0'
useLibrary 'org.apache.http.legacy'
@@ -84,8 +84,4 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
def shizuku_version = "13.1.5"
implementation "dev.rikka.shizuku:api:$shizuku_version"
implementation "dev.rikka.shizuku:provider:$shizuku_version"
}
+1 -10
View File
@@ -82,8 +82,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
dev.shadoe.delta.action.START_SOFT_AP
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
@@ -275,14 +274,6 @@
android:exported="true"
/>
<provider
android:name="rikka.shizuku.ShizukuProvider"
android:authorities="${applicationId}.shizuku"
android:enabled="true"
android:exported="true"
android:multiprocess="false"
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />
<service android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
@@ -18,7 +18,6 @@ import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.TetheringManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Build;
@@ -74,8 +73,6 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
@@ -544,7 +541,7 @@ public class Actions
}
}
}
else if(Build.VERSION.SDK_INT < 36)
else
{
MyOnStartTetheringCallback cb = new MyOnStartTetheringCallback()
{
@@ -567,13 +564,6 @@ public class Actions
else
mowm.stopTethering();
}
else // from Android 16 onwards
{
if(desiredState)
Actions.WifiTethering.enable(context);
else
Actions.WifiTethering.disable(context);
}
}
return true;
}
@@ -1232,11 +1222,8 @@ public class Actions
else if (startupType.equals(ActivityManageActionStartActivity.startByForegroundServiceString) && Build.VERSION.SDK_INT >= 26)
automationServerRef.startForegroundService(externalApplicationIntent);
else
{
externalApplicationIntent.addCategory("");
automationServerRef.sendBroadcast(externalApplicationIntent);
}
}
catch (Exception e)
{
Miscellaneous.logEvent("e", "StartOtherApp", automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2);
@@ -2687,71 +2674,5 @@ public class Actions
// }
android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, String.valueOf(desiredState));
}
public static final class WifiTethering
{
private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
private WifiTethering()
{
// Utility class
}
public static void enable(Context context)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.BAKLAVA)
{
throw new UnsupportedOperationException("TetheringManager requires Android 16 / API 36");
}
TetheringManager tetheringManager = context.getSystemService(TetheringManager.class);
TetheringManager.TetheringRequest request = new TetheringManager.TetheringRequest.Builder(TetheringManager.TETHERING_WIFI).build();
tetheringManager.startTethering(request, EXECUTOR, new TetheringManager.StartTetheringCallback() {
@Override
public void onTetheringStarted()
{
// Wi-Fi hotspot enabled
Miscellaneous.logEvent("i", "Tethering start", "Success", 3);
}
@Override
public void onTetheringFailed(int error)
{
// Hotspot could not be enabled
Miscellaneous.logEvent("i", "Tethering start", "Failure. Error code: " + String.valueOf(error), 3);
}
}
);
}
public static void disable(Context context)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.BAKLAVA)
{
throw new UnsupportedOperationException("TetheringManager requires Android 16 / API 36");
}
TetheringManager tetheringManager = context.getSystemService(TetheringManager.class);
TetheringManager.TetheringRequest request = new TetheringManager.TetheringRequest.Builder(TetheringManager.TETHERING_WIFI).build();
// tetheringManager.stopTethering(TetheringManager.TETHERING_WIFI, EXECUTOR, new TetheringManager.StopTetheringCallback() {
tetheringManager.stopTethering(request, EXECUTOR, new TetheringManager.StopTetheringCallback() {
@Override
public void onStopTetheringSucceeded()
{
TetheringManager.StopTetheringCallback.super.onStopTetheringSucceeded();
Miscellaneous.logEvent("i", "Tethering stop", "Success", 3);
}
@Override
public void onStopTetheringFailed(int error)
{
// Hotspot could not be disabled
Miscellaneous.logEvent("i", "Tethering stop", "Failure. Error code: " + String.valueOf(error), 3);
}
}
);
}
}
}
@@ -6,6 +6,9 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
@@ -27,9 +30,13 @@ import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Text;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Pattern;
public class ActivityManageActionTriggerUrl extends Activity
{
@@ -39,7 +46,7 @@ public class ActivityManageActionTriggerUrl extends Activity
CheckBox chkTriggerUrlUseAuthentication;
RadioButton rbTriggerUrlMethodGet, rbTriggerUrlMethodPost;
TableLayout tlTriggerUrlAuthentication;
TextView tvHttpParameterExplanation;
TextView tvHttpParameterExplanation, tvUrlValidator;
ArrayAdapter<String> httpParametersAdapter;
private ArrayList<String> httpParamsList = new ArrayList<>();
@@ -70,6 +77,7 @@ public class ActivityManageActionTriggerUrl extends Activity
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
bAddHttpParam = (Button)findViewById(R.id.bAddHttpParam);
tvHttpParameterExplanation = (TextView)findViewById(R.id.tvHttpParameterExplanation);
tvUrlValidator = (TextView)findViewById(R.id.tvUrlValidator);
etParameterName.setEnabled(false);
etParameterValue.setEnabled(false);
@@ -173,6 +181,33 @@ public class ActivityManageActionTriggerUrl extends Activity
});
updateListView();
etTriggerUrl.addTextChangedListener(new TextWatcher()
{
@Override
public void afterTextChanged(Editable editable)
{
if(etTriggerUrl.getText() != null && etTriggerUrl.getText().length() > 0)
{
if(Miscellaneous.isValidUrl(etTriggerUrl.getText().toString()))
tvUrlValidator.setText("");
else
tvUrlValidator.setText(getResources().getString(R.string.enter_valid_url));
}
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
});
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
{
// username,password,URL,etc.
@@ -105,6 +105,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@@ -133,6 +135,9 @@ public class Miscellaneous extends Service
protected final static String httpMainData = "httpMainData";
protected final static String doNoEncodingString = "NoEncoding";
protected final static String httpEncoding = "UTF-8";
protected final static String URL_REGEX = "^(https?):\\/\\/([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)(:[0-9]{1,5})?([\\/\\?#].*)?$";
// protected final static String URL_REGEX = "^(https?|ftp):\\/\\/([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)(:[0-9]{1,5})?([\\/\\?#].*)?$";
protected final static Pattern URL_PATTERN = Pattern.compile(URL_REGEX, Pattern.CASE_INSENSITIVE);
public static Context startupContext;
public static final String lineSeparator = System.getProperty("line.separator");
@@ -2428,4 +2433,13 @@ public class Miscellaneous extends Service
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
public static boolean isValidUrl(String input)
{
if (input == null || input.length() == 0)
return false;
Matcher matcher = URL_PATTERN.matcher(input);
return matcher.matches(); // Returns true if the entire string matches
}
}
@@ -35,6 +35,12 @@
</EditText>
<TextView
android:id="@+id/tvUrlValidator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/red" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+1 -1
View File
@@ -887,5 +887,5 @@
<string name="enterAvalue">Geben Sie einen Wert ein.</string>
<string name="setSystemSettingCapital">Systemeinstellung setzen</string>
<string name="examplesWriteSecureSettings">Ich führe keine Liste möglicher Einstellungen. Bitte finden Sie diese Einstellungen selbst. Siehe <a href="https://developer.android.com/reference/android/provider/Settings.Secure">hier</a> für einige (unvollständige) Beispiele.</string>
<string name="httpParametersExplanation">Beginnt ein Parametername mit %1$s, während die Methode POST ist, wird er nicht wie die anderen Parameter (mit Schlüssel=Wert) übertragen, sondern als Hauptdaten übertragen. Wenn der Parameter mit 2 % endet, wird keine Codierung durchgeführt.</string>
<string name="httpParametersExplanation">Beginnt ein Parametername mit %1$s, während die Methode POST ist, wird er nicht wie die anderen Parameter (mit Schlüssel=Wert) übertragen, sondern als Hauptdaten übertragen. Wenn der Parameter mit %2$s endet, wird keine Codierung durchgeführt.</string>
</resources>
+1
View File
@@ -979,4 +979,5 @@
<string name="examplesWriteSecureSettings">I do not keep a list of possible settings. Please find those settings on your own. See <a href="https://developer.android.com/reference/android/provider/Settings.Secure">here</a> for some (incomplete) examples.</string>
<string name="httpParametersExplanation">If any parameter name starts with %1$s while method is POST, it will not be transmitted like the other parameters (with key=value), but transferred as main data. If the parameter ends with %2$s, no encoding will be performed.</string>
<string name="target">Target</string>
<string name="enter_valid_url">Enter a valid URL.</string>
</resources>
@@ -1 +1,3 @@
* Added: Triggers and actions can now be cloned
* Added: URL checker for triggerUrl action
* Fixed: Crash when starting to add/edit a triggerURL action while the app or the system are set to the German language