diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml index 6bca09c5..5c59e0cf 100644 --- a/app/src/apkFlavor/AndroidManifest.xml +++ b/app/src/apkFlavor/AndroidManifest.xml @@ -166,6 +166,9 @@ + + + diff --git a/app/src/fdroidFlavor/AndroidManifest.xml b/app/src/fdroidFlavor/AndroidManifest.xml index 77a006c8..47a480d7 100644 --- a/app/src/fdroidFlavor/AndroidManifest.xml +++ b/app/src/fdroidFlavor/AndroidManifest.xml @@ -164,6 +164,9 @@ + + + diff --git a/app/src/googlePlayFlavor/AndroidManifest.xml b/app/src/googlePlayFlavor/AndroidManifest.xml index 5d60ad4a..8410205e 100644 --- a/app/src/googlePlayFlavor/AndroidManifest.xml +++ b/app/src/googlePlayFlavor/AndroidManifest.xml @@ -151,6 +151,9 @@ + + + diff --git a/app/src/main/java/com/jens/automation2/Action.java b/app/src/main/java/com/jens/automation2/Action.java index bb597f6d..ff8b1e14 100644 --- a/app/src/main/java/com/jens/automation2/Action.java +++ b/app/src/main/java/com/jens/automation2/Action.java @@ -52,6 +52,7 @@ public class Action createNotification, closeNotification, sendBroadcast, + runExecutable, sendTextMessage; public String getFullName(Context context) @@ -124,6 +125,8 @@ public class Action return context.getResources().getString(R.string.closeNotifications); case sendBroadcast: return context.getResources().getString(R.string.sendBroadcast); + case runExecutable: + return context.getResources().getString(R.string.runExecutable); default: return "Unknown"; } @@ -267,6 +270,9 @@ public class Action case sendBroadcast: returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.sendBroadcast)); break; + case runExecutable: + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.runExecutable)); + break; default: returnString.append(action.toString()); } @@ -324,7 +330,15 @@ 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]); - + } + else if(this.getAction().equals(Action_Enum.setWifi)) + { + if(!StringUtils.isEmpty(this.parameter2)) + { + boolean useRoot = Boolean.parseBoolean(this.parameter2); + if(useRoot) + returnString.append(" " + Miscellaneous.getAnyContext().getResources().getString(R.string.usingRoot)); + } } else if(this.getAction().equals(Action_Enum.controlMediaPlayback)) { @@ -354,6 +368,10 @@ public class Action returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.unknown)); } } + else if(this.getAction().equals(Action_Enum.sendBroadcast)) + { + returnString.append(": " + parameter2.replace(Action.actionParameter2Split, "; ").replace(Action.intentPairSeparator, "/")); + } else if (parameter2 != null && parameter2.length() > 0) returnString.append(": " + parameter2.replace(Action.actionParameter2Split, "; ")); } @@ -545,6 +563,13 @@ public class Action case sendBroadcast: Actions.sendBroadcast(context, this.getParameter2()); break; + case runExecutable: + String[] execParts = this.getParameter2().split(Action.actionParameter2Split); + if(execParts.length == 1) + Actions.runExecutable(context, this.getParameter1(), execParts[0], null); + else if(execParts.length == 2) + Actions.runExecutable(context, this.getParameter1(), execParts[0], execParts[1]); + break; default: Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3); break; diff --git a/app/src/main/java/com/jens/automation2/Actions.java b/app/src/main/java/com/jens/automation2/Actions.java index d3c0d5f7..535cd44b 100644 --- a/app/src/main/java/com/jens/automation2/Actions.java +++ b/app/src/main/java/com/jens/automation2/Actions.java @@ -52,7 +52,12 @@ import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.util.InetAddressUtils; import org.apache.http.impl.client.DefaultHttpClient; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -62,8 +67,11 @@ import java.net.NetworkInterface; import java.security.KeyStore; import java.util.Calendar; import java.util.Collections; +import java.util.Enumeration; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; @@ -189,7 +197,18 @@ public class Actions { Miscellaneous.logEvent("i", "sendBroadcast", "Sending broadcast with action " + action, 5); Intent broadcastIntent = new Intent(); - broadcastIntent.setAction(action); + + if(action.contains(Action.actionParameter2Split)) + { + String[] parts = action.split(Action.actionParameter2Split); + broadcastIntent.setAction(parts[0]); + + String[] intentparts = parts[1].split(";"); + broadcastIntent = packParametersIntoIntent(broadcastIntent, intentparts, 0); + } + else + broadcastIntent.setAction(action); + context.sendBroadcast(broadcastIntent); } @@ -1000,8 +1019,6 @@ public class Actions { Intent externalActivityIntent; - int paramsStartIndex; - if (!startByAction) { // selected by activity @@ -1013,8 +1030,6 @@ public class Actions Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by activity: " + packageName + " " + className, 3); - paramsStartIndex = 2; - externalActivityIntent = new Intent(Intent.ACTION_MAIN); externalActivityIntent.addCategory(Intent.CATEGORY_LAUNCHER); @@ -1042,86 +1057,7 @@ public class Actions externalActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Pack intents - for (int i = 3; i < params.length; i++) - { - String[] singleParam = params[i].split(Action.intentPairSeparator); - - /*Class c = Class.forName(singleParam[0]); - for(Method m : c.getMethods()) - { - if(m.getName().startsWith("parse")) - { - Object o = m.invoke(null, singleParam[0]); - externalActivityIntent.putExtra(singleParam[1], o); - } - }*/ - - if (singleParam[0].equals("boolean")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Boolean.parseBoolean(singleParam[2])); - } - else if (singleParam[0].equals("byte")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Byte.parseByte(singleParam[2])); - } - else if (singleParam[0].equals("char")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], singleParam[2].charAt(0)); - } - else if (singleParam[0].equals("CharSequence")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], (CharSequence) singleParam[2]); - } - else if (singleParam[0].equals("double")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Double.parseDouble(singleParam[2])); - } - else if (singleParam[0].equals("float")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Float.parseFloat(singleParam[2])); - } - else if (singleParam[0].equals("int")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Integer.parseInt(singleParam[2])); - } - else if (singleParam[0].equals("long")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Long.parseLong(singleParam[2])); - } - else if (singleParam[0].equals("short")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Short.parseShort(singleParam[2])); - } - else if (singleParam[0].equals("Uri")) - { - if (singleParam[1].equalsIgnoreCase("IntentData")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with value " + singleParam[2] + " as standard data parameter.", 3); - externalActivityIntent.setData(Uri.parse(singleParam[2])); - } - else - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], Uri.parse(singleParam[2])); - } - } - else if (singleParam[0].equals("String")) - { - Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); - externalActivityIntent.putExtra(singleParam[1], singleParam[2]); - } - else - Miscellaneous.logEvent("w", "StartOtherApp", "Unknown type of parameter " + singleParam[0] + " found. Name " + singleParam[1] + " and value " + singleParam[2], 3); - } + externalActivityIntent = packParametersIntoIntent(externalActivityIntent, params, 3); if (params[2].equals(ActivityManageActionStartActivity.startByActivityString)) automationServerRef.startActivity(externalActivityIntent); @@ -1135,6 +1071,92 @@ public class Actions } } + public static Intent packParametersIntoIntent(Intent intent, String[] params, int startIndex) + { + for (int i = startIndex; i < params.length; i++) + { + String[] singleParam = params[i].split(Action.intentPairSeparator); + + /*Class c = Class.forName(singleParam[0]); + for(Method m : c.getMethods()) + { + if(m.getName().startsWith("parse")) + { + Object o = m.invoke(null, singleParam[0]); + externalActivityIntent.putExtra(singleParam[1], o); + } + }*/ + + if (singleParam[0].equals("boolean")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Boolean.parseBoolean(singleParam[2])); + } + else if (singleParam[0].equals("byte")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Byte.parseByte(singleParam[2])); + } + else if (singleParam[0].equals("char")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], singleParam[2].charAt(0)); + } + else if (singleParam[0].equals("CharSequence")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], (CharSequence) singleParam[2]); + } + else if (singleParam[0].equals("double")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Double.parseDouble(singleParam[2])); + } + else if (singleParam[0].equals("float")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Float.parseFloat(singleParam[2])); + } + else if (singleParam[0].equals("int")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Integer.parseInt(singleParam[2])); + } + else if (singleParam[0].equals("long")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Long.parseLong(singleParam[2])); + } + else if (singleParam[0].equals("short")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Short.parseShort(singleParam[2])); + } + else if (singleParam[0].equals("Uri")) + { + if (singleParam[1].equalsIgnoreCase("IntentData")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with value " + singleParam[2] + " as standard data parameter.", 3); + intent.setData(Uri.parse(singleParam[2])); + } + else + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], Uri.parse(singleParam[2])); + } + } + else if (singleParam[0].equals("String")) + { + Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with name " + singleParam[1] + " and value " + singleParam[2], 3); + intent.putExtra(singleParam[1], singleParam[2]); + } + else + Miscellaneous.logEvent("w", "StartOtherApp", "Unknown type of parameter " + singleParam[0] + " found. Name " + singleParam[1] + " and value " + singleParam[2], 3); + } + + return intent; + } + public static void waitBeforeNextAction(Long waitTime) { Miscellaneous.logEvent("i", "waitBeforeNextAction", "waitBeforeNextAction for " + String.valueOf(waitTime) + " milliseconds.", 4); @@ -1907,4 +1929,187 @@ public class Actions return android.provider.Settings.Global.getInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, 0) != 0; } } + + public static boolean runExecutable(Context context, boolean runAsRoot, String path, String parameters) + { + if(runAsRoot) + { + if(!StringUtils.isEmpty(parameters)) + return executeCommandViaSu(new String[] { path + " " + parameters }); + else + return executeCommandViaSu(new String[] { path }); + } + else + { + Object[] result; + + File executable = new File(path); + File workingDir = new File(executable.getParent()); + + if(!StringUtils.isEmpty(parameters)) + result = runExternalApplication(path, 0, workingDir, parameters); + else + result = runExternalApplication(path, 0, workingDir, null); + + boolean execResult = (boolean) result[0]; + + return execResult; + } + } + + /** + * + * @param commandToExecute + * @param timeout + * @param params + * @return Returns an array: 0=exit code, 1=cmdline output + */ + public static Object[] runExternalApplication(String commandToExecute, long timeout, File workingDirectory, String params) + { + /* + * Classes stolen from https://github.com/stleary/JSON-java + */ + + String fullCommand; + + if(!StringUtils.isEmpty(params)) + fullCommand = commandToExecute + " " + params; + else + fullCommand = commandToExecute; + + Miscellaneous.logEvent("i", "Running executable", "Running external application " + fullCommand, 4); + + Object[] returnObject = new Object[2]; + + StringBuilder output = new StringBuilder(); + String line = null; + OutputStream stdin = null; + InputStream stderr = null; + InputStream stdout = null; + + try + { + Process process = null; + + if(workingDirectory != null) + process = Runtime.getRuntime().exec(fullCommand, null, workingDirectory); + else + process = Runtime.getRuntime().exec(fullCommand); + stdin = process.getOutputStream (); + stderr = process.getErrorStream (); + stdout = process.getInputStream (); + + // "write" the parms into stdin + /*line = "param1" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush(); + + line = "param2" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush(); + + line = "param3" + "\n"; + stdin.write(line.getBytes() ); + stdin.flush();*/ + + stdin.close(); + + // clean up if any output in stdout + BufferedReader brCleanUp = new BufferedReader (new InputStreamReader (stdout)); + while ((line = brCleanUp.readLine ()) != null) + { + Miscellaneous.logEvent ("i", "Running executable", "[Stdout] " + line, 4); + output.append(line); + } + brCleanUp.close(); + + // clean up if any output in stderr + brCleanUp = new BufferedReader (new InputStreamReader(stderr)); + while ((line = brCleanUp.readLine ()) != null) + { + Miscellaneous.logEvent ("i", "Running executable", "[Stderr] " + line, 4); + output.append(line); + } + brCleanUp.close(); + + try + { + // Wait for the process to exit, we want the return code + if(timeout > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + { + try + { + if(!process.waitFor(timeout, TimeUnit.MILLISECONDS)) + { + Miscellaneous.logEvent("i", "Running executable", "Timeout of " + String.valueOf(timeout) + " ms reached. Killing check attempt.", 3); + process.destroyForcibly(); + } + } + catch(NoSuchMethodError e) + { + process.waitFor(); + } + } + else + process.waitFor(); + } + catch (InterruptedException e) + { + Miscellaneous.logEvent("i", "Running executable", "Waiting for process failed: " + Log.getStackTraceString(e), 4); + Miscellaneous.logEvent("i", "Running executable", Log.getStackTraceString(e), 1); + } + + if(process.exitValue() == 0) + Miscellaneous.logEvent("i", "Running executable", "ReturnCode: " + String.valueOf(process.exitValue()), 4); + else + Miscellaneous.logEvent("i", "Running executable", "External execution (RC=" + String.valueOf(process.exitValue()) + ") returned error: " + output.toString(), 3); + + returnObject[0] = process.exitValue(); + returnObject[1] = output.toString(); + + return returnObject; + } + catch (IOException e) + { + Miscellaneous.logEvent("e", "Running executable", Log.getStackTraceString(e), 1); + } + + Miscellaneous.logEvent("i", "Running executable", "Error running external application.", 1); + +// if(slotMap != null) +// for(String key : slotMap.keySet()) +// System.clearProperty(key); + + return null; + } + + public static boolean isTetheringActive1(Context context) + { + try + { + for(Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) + { + NetworkInterface intf = en.nextElement(); + + for(Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) + { + InetAddress inetAddress = enumIpAddr.nextElement(); + + if(!intf.isLoopback()) + { + if(intf.getName().contains("rndis")) + { + return true; + } + } + } + } + } + catch(Exception e) + { + Miscellaneous.logEvent("e", "isTetheringActive()", Log.getStackTraceString(e), 3); + } + + return false; + } } \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityControlCenter.java b/app/src/main/java/com/jens/automation2/ActivityControlCenter.java index 06a18339..0a6de714 100644 --- a/app/src/main/java/com/jens/automation2/ActivityControlCenter.java +++ b/app/src/main/java/com/jens/automation2/ActivityControlCenter.java @@ -357,7 +357,7 @@ public class ActivityControlCenter extends Activity systemInfoText.append("Device: " + android.os.Build.DEVICE + Miscellaneous.lineSeparator); systemInfoText.append("Model: " + android.os.Build.MODEL + Miscellaneous.lineSeparator); systemInfoText.append("Product: " + android.os.Build.PRODUCT + Miscellaneous.lineSeparator); - systemInfoText.append("Rooted: " + String.valueOf(Miscellaneous.isPhoneRooted())); + systemInfoText.append("Rooted: " + String.valueOf(Miscellaneous.isPhoneRooted()) + Miscellaneous.lineSeparator); systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator); systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName() + Miscellaneous.lineSeparator); systemInfoText.append("Logfile written: " + String.valueOf(Settings.writeLogFile) + Miscellaneous.lineSeparator); diff --git a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java index 909bec9d..54f8ad4f 100644 --- a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java +++ b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java @@ -77,10 +77,9 @@ public class ActivityMainScreen extends ActivityGeneric tvLockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration); tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound); toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener); - bDonate = (Button)findViewById(R.id.bDonate); - if(!BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor")) + if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay)) bDonate.setVisibility(View.VISIBLE); toggleService.setChecked(AutomationService.isMyServiceRunning(this)); diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionRunExecutable.java b/app/src/main/java/com/jens/automation2/ActivityManageActionRunExecutable.java new file mode 100644 index 00000000..1111e043 --- /dev/null +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionRunExecutable.java @@ -0,0 +1,114 @@ +package com.jens.automation2; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.Nullable; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; + +public class ActivityManageActionRunExecutable extends Activity +{ + final static int PICKFILE_RESULT_CODE = 4711; + + CheckBox chkRunExecAsRoot; + EditText etRunExecutablePath, etRunExecutableParameters; + Button bChooseExecutable, bSaveActionRunExec; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_action_run_executable); + + chkRunExecAsRoot = (CheckBox)findViewById(R.id.chkRunExecAsRoot); + etRunExecutablePath = (EditText) findViewById(R.id.etRunExecutablePath); + etRunExecutableParameters = (EditText) findViewById(R.id.etRunExecutableParameters); + bChooseExecutable = (Button) findViewById(R.id.bChooseExecutable); + bSaveActionRunExec = (Button) findViewById(R.id.bSaveActionRunExec); + + bChooseExecutable.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + //Need to check for storage permissions + Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT); + chooseFile.setType("*/*"); + chooseFile = Intent.createChooser(chooseFile, getResources().getString(R.string.selectSoundFile)); + startActivityForResult(chooseFile, PICKFILE_RESULT_CODE); + } + }); + + bSaveActionRunExec.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View view) + { + saveExecSettings(); + } + }); + } + + void saveExecSettings() + { + if(etRunExecutablePath.getText().toString() == null || etRunExecutablePath.getText().toString().length() == 0) + { + Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.selectValidExecutable), Toast.LENGTH_LONG).show(); + return; + } + else + { + File executableFile = new File(etRunExecutablePath.getText().toString()); + if(!executableFile.exists()) + { + Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.fileDoesNotExist), Toast.LENGTH_LONG).show(); + return; + } + else + { + if(!chkRunExecAsRoot.isChecked() && !executableFile.canExecute()) + { + Toast.makeText(ActivityManageActionRunExecutable.this, getResources().getString(R.string.fileNotExecutable), Toast.LENGTH_LONG).show(); + return; + } + } + } + + Intent returnData = new Intent(); + returnData.putExtra(ActivityManageRule.intentNameActionParameter1, chkRunExecAsRoot.isChecked()); + + if(etRunExecutableParameters.getText() != null && !StringUtils.isEmpty(etRunExecutableParameters.getText().toString())) + returnData.putExtra(ActivityManageRule.intentNameActionParameter2, etRunExecutablePath.getText().toString() + Action.actionParameter2Split + etRunExecutableParameters.getText().toString()); + else + returnData.putExtra(ActivityManageRule.intentNameActionParameter2, etRunExecutablePath.getText().toString()); + + setResult(RESULT_OK, returnData); + finish(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + super.onActivityResult(requestCode, resultCode, data); + + if(resultCode == RESULT_OK) + { + if(requestCode == PICKFILE_RESULT_CODE) + { + Uri fileUri = data.getData(); + String filePath = CompensateCrappyAndroidPaths.getPath(ActivityManageActionRunExecutable.this, fileUri); + etRunExecutablePath.setText(filePath); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionSendBroadcast.java b/app/src/main/java/com/jens/automation2/ActivityManageActionSendBroadcast.java index f346984d..16b4c8c9 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionSendBroadcast.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionSendBroadcast.java @@ -5,19 +5,33 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.text.InputType; import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; +import android.widget.ListView; +import android.widget.Spinner; import android.widget.Toast; import androidx.annotation.Nullable; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; +import java.util.List; + public class ActivityManageActionSendBroadcast extends Activity { EditText etBroadcastToSend; - Button bBroadcastSendShowSuggestions, bSaveSendBroadcast; + Button bBroadcastSendShowSuggestions, bSaveSendBroadcast, bAddIntentPair; + ListView lvIntentPairs; + EditText etParameterName, etParameterValue; + Spinner spinnerParameterType; + ArrayAdapter intentTypeSpinnerAdapter, intentPairAdapter; + private static final String[] supportedIntentTypes = { "boolean", "byte", "char", "double", "float", "int", "long", "short", "String", "Uri" }; + private ArrayList intentPairList = new ArrayList<>(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) @@ -28,6 +42,16 @@ public class ActivityManageActionSendBroadcast extends Activity etBroadcastToSend = (EditText)findViewById(R.id.etBroadcastToSend); bBroadcastSendShowSuggestions = (Button)findViewById(R.id.bBroadcastSendShowSuggestions); bSaveSendBroadcast = (Button)findViewById(R.id.bSaveSendBroadcast); + bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair); + lvIntentPairs = (ListView) findViewById(R.id.lvIntentPairs); + etParameterName = (EditText) findViewById(R.id.etParameterName); + etParameterValue = (EditText) findViewById(R.id.etParameterValue); + spinnerParameterType = (Spinner) findViewById(R.id.spinnerParameterType); + + intentTypeSpinnerAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionSendBroadcast.supportedIntentTypes); + spinnerParameterType.setAdapter(intentTypeSpinnerAdapter); + intentTypeSpinnerAdapter.notifyDataSetChanged(); + intentPairAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList); bSaveSendBroadcast.setOnClickListener(new View.OnClickListener() { @@ -37,7 +61,20 @@ public class ActivityManageActionSendBroadcast extends Activity if(checkInput()) { Intent answer = new Intent(); - answer.putExtra(ActivityManageRule.intentNameActionParameter2, etBroadcastToSend.getText().toString()); + + String param2 = etBroadcastToSend.getText().toString(); + + if(intentPairList.size() > 0) + { + param2 += Action.actionParameter2Split; + + for (String s : intentPairList) + param2 += s + ";"; + + param2 = param2.substring(0, param2.length() - 1); + } + + answer.putExtra(ActivityManageRule.intentNameActionParameter2, param2); setResult(RESULT_OK, answer); finish(); } @@ -66,7 +103,117 @@ public class ActivityManageActionSendBroadcast extends Activity Intent input = getIntent(); if(input.hasExtra(ActivityManageRule.intentNameActionParameter2)) - etBroadcastToSend.setText(input.getStringExtra(ActivityManageRule.intentNameActionParameter2)); + { + String param2 = input.getStringExtra(ActivityManageRule.intentNameActionParameter2); + if(!param2.contains(Action.actionParameter2Split)) + etBroadcastToSend.setText(input.getStringExtra(ActivityManageRule.intentNameActionParameter2)); + else + { + String[] param2Parts = param2.split(Action.actionParameter2Split); + etBroadcastToSend.setText(param2Parts[0]); + + String[] params = param2Parts[1].split(";"); + + intentPairList.clear(); + + for(int i = 0; i < params.length; i++) + { + if(lvIntentPairs.getVisibility() != View.VISIBLE) + lvIntentPairs.setVisibility(View.VISIBLE); + + intentPairList.add(params[i]); + } + + updateIntentPairList(); + } + } + + bAddIntentPair.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + // type;name;value + if(spinnerParameterType.getSelectedItem().toString().length() == 0) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show(); + return; + } + + if(etParameterName.getText().toString().length() == 0) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterName.getText().toString().contains(Action.intentPairSeparator)) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterName.getText().toString().contains(";")) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); + return; + } + + if(etParameterValue.getText().toString().length() == 0) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator)) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterValue.getText().toString().contains(";")) + { + Toast.makeText(ActivityManageActionSendBroadcast.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); + return; + } + + String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString(); + intentPairList.add(param); + + spinnerParameterType.setSelection(0); + etParameterName.setText(""); + etParameterValue.setText(""); + + updateIntentPairList(); + + if(lvIntentPairs.getVisibility() != View.VISIBLE) + lvIntentPairs.setVisibility(View.VISIBLE); + } + }); + + lvIntentPairs.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() + { + @Override + public boolean onItemLongClick(AdapterView arg0, View arg1, int arg2, long arg3) + { + getIntentPairDialog(arg2).show(); + return false; + } + }); + + spinnerParameterType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() + { + @Override + public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) + { + if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short")) + ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER); + else + ActivityManageActionSendBroadcast.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT); + } + + @Override + public void onNothingSelected(AdapterView arg0) + { + // TODO Auto-generated method stub + + } + }); } boolean checkInput() @@ -80,4 +227,30 @@ public class ActivityManageActionSendBroadcast extends Activity return true; } + + private void updateIntentPairList() + { + if(lvIntentPairs.getAdapter() == null) + lvIntentPairs.setAdapter(intentPairAdapter); + + intentPairAdapter.notifyDataSetChanged(); + } + + private AlertDialog getIntentPairDialog(final int itemPosition) + { + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ActivityManageActionSendBroadcast.this); + alertDialogBuilder.setTitle(getResources().getString(R.string.whatToDoWithIntentPair)); + alertDialogBuilder.setItems(new String[]{getResources().getString(R.string.delete)}, new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + // Only 1 choice at the moment, no need to check + ActivityManageActionSendBroadcast.this.intentPairList.remove(itemPosition); + updateIntentPairList(); + } + }); + AlertDialog alertDialog = alertDialogBuilder.create(); + return alertDialog; + } } \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionSpeakText.java b/app/src/main/java/com/jens/automation2/ActivityManageActionSpeakText.java index cb23f2e9..f9e8bd45 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionSpeakText.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionSpeakText.java @@ -15,8 +15,6 @@ public class ActivityManageActionSpeakText extends Activity private Button bSaveSpeakText; private EditText etSpeakText; -// private String existingUrl = ""; - public static boolean edit = false; public static Action resultingAction = null; @@ -27,7 +25,7 @@ public class ActivityManageActionSpeakText extends Activity this.setContentView(R.layout.activity_manage_action_speak_text); etSpeakText = (EditText)findViewById(R.id.etTextToSpeak); - bSaveSpeakText = (Button)findViewById(R.id.bSaveTriggerUrl); + bSaveSpeakText = (Button)findViewById(R.id.bSaveSpeakText); bSaveSpeakText.setOnClickListener(new OnClickListener() { @Override diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java b/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java index cc0dd2eb..4e6b628f 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java @@ -60,6 +60,202 @@ public class ActivityManageActionStartActivity extends Activity final static String startByBroadcastString = "1"; final static int requestCodeForRequestQueryAllPackagesPermission = 4711; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_action_start_activity); + + lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs); + etParameterName = (EditText)findViewById(R.id.etParameterName); + etParameterValue = (EditText)findViewById(R.id.etParameterValue); + bSelectApp = (Button)findViewById(R.id.bSelectApp); + bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair); + bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity); + spinnerParameterType = (Spinner)findViewById(R.id.spinnerParameterType); + etPackageName = (EditText) findViewById(R.id.etPackageName); + etActivityOrActionPath = (EditText) findViewById(R.id.etActivityOrActionPath); + rbStartAppSelectByActivity = (RadioButton)findViewById(R.id.rbStartAppSelectByActivity); + rbStartAppSelectByAction = (RadioButton)findViewById(R.id.rbStartAppSelectByAction); + showStartProgramExamples = (Button)findViewById(R.id.showStartProgramExamples); + rbStartAppByActivity = (RadioButton)findViewById(R.id.rbStartAppByActivity); + rbStartAppByBroadcast = (RadioButton)findViewById(R.id.rbStartAppByBroadcast); + + intentTypeSpinnerAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionStartActivity.supportedIntentTypes); + spinnerParameterType.setAdapter(intentTypeSpinnerAdapter); + intentTypeSpinnerAdapter.notifyDataSetChanged(); + + intentPairAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList); + + bSelectApp.setOnClickListener(new OnClickListener() + { + @Override + public void onClick(View v) + { + int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion; + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && targetSdkVersion >= 30 && !ActivityPermissions.havePermission(Manifest.permission.QUERY_ALL_PACKAGES, ActivityManageActionStartActivity.this))// && shouldShowRequestPermissionRationale(Manifest.permission.QUERY_ALL_PACKAGES)) + { + if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay)) + { + // This ain't possible anymore. + Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.featureNotInGooglePlayVersion) + Miscellaneous.lineSeparator + Miscellaneous.lineSeparator + getResources().getString(R.string.startActivityInsertManually), ActivityManageActionStartActivity.this).show(); + } + else + requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission); + } + else + getAppList(); + } + }); + + bAddIntentPair.setOnClickListener(new OnClickListener() + { + @Override + public void onClick(View v) + { + // type;name;value + if(spinnerParameterType.getSelectedItem().toString().length() == 0) + { + Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show(); + return; + } + + if(etParameterName.getText().toString().length() == 0) + { + Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterName.getText().toString().contains(Action.intentPairSeparator)) + { + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterName.getText().toString().contains(";")) + { + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); + return; + } + + if(etParameterValue.getText().toString().length() == 0) + { + Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator)) + { + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); + return; + } + else if(etParameterValue.getText().toString().contains(";")) + { + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); + return; + } + + String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString(); + intentPairList.add(param); + + spinnerParameterType.setSelection(0); + etParameterName.setText(""); + etParameterValue.setText(""); + + updateIntentPairList(); + + if(lvIntentPairs.getVisibility() != View.VISIBLE) + lvIntentPairs.setVisibility(View.VISIBLE); + } + }); + + showStartProgramExamples.setOnClickListener(new OnClickListener() + { + @Override + public void onClick(View v) + { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlShowExamples)); + startActivity(browserIntent); + } + }); + + lvIntentPairs.setOnItemLongClickListener(new OnItemLongClickListener() + { + @Override + public boolean onItemLongClick(AdapterView arg0, View arg1, int arg2, long arg3) + { + getIntentPairDialog(arg2).show(); + return false; + } + }); + + bSaveActionStartOtherActivity.setOnClickListener(new OnClickListener() + { + @Override + public void onClick(View v) + { + if(saveAction()) + { + ActivityManageActionStartActivity.this.setResult(RESULT_OK); + finish(); + } + } + }); + + lvIntentPairs.setOnTouchListener(new OnTouchListener() + { + @Override + public boolean onTouch(View v, MotionEvent event) + { + v.getParent().requestDisallowInterceptTouchEvent(true); + return false; + } + }); + + spinnerParameterType.setOnItemSelectedListener(new OnItemSelectedListener() + { + @Override + public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) + { + if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short")) + ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER); + else + ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT); + } + + @Override + public void onNothingSelected(AdapterView arg0) + { + // TODO Auto-generated method stub + + } + }); + + rbStartAppSelectByActivity.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() + { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) + { + if(isChecked) + bSelectApp.setEnabled(isChecked); + } + }); + + rbStartAppSelectByAction.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() + { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) + { + if(isChecked) + bSelectApp.setEnabled(!isChecked); + } + }); + + Intent i = getIntent(); + if(i.getBooleanExtra("edit", false) == true) + { + edit = true; + loadValuesIntoGui(); + } + } private class CustomPackageInfo extends PackageInfo implements Comparable { @@ -82,7 +278,6 @@ public class ActivityManageActionStartActivity extends Activity return name1.compareTo(name2); } - } private static List pInfos = null; @@ -343,203 +538,6 @@ public class ActivityManageActionStartActivity extends Activity getActivityListTask.execute(); progressDialog = ProgressDialog.show(ActivityManageActionStartActivity.this, "", ActivityManageActionStartActivity.this.getResources().getString(R.string.gettingListOfInstalledApplications)); } - - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_manage_action_start_activity); - - lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs); - etParameterName = (EditText)findViewById(R.id.etParameterName); - etParameterValue = (EditText)findViewById(R.id.etParameterValue); - bSelectApp = (Button)findViewById(R.id.bSelectApp); - bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair); - bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity); - spinnerParameterType = (Spinner)findViewById(R.id.spinnerParameterType); - etPackageName = (EditText) findViewById(R.id.etPackageName); - etActivityOrActionPath = (EditText) findViewById(R.id.etActivityOrActionPath); - rbStartAppSelectByActivity = (RadioButton)findViewById(R.id.rbStartAppSelectByActivity); - rbStartAppSelectByAction = (RadioButton)findViewById(R.id.rbStartAppSelectByAction); - showStartProgramExamples = (Button)findViewById(R.id.showStartProgramExamples); - - rbStartAppByActivity = (RadioButton)findViewById(R.id.rbStartAppByActivity); - rbStartAppByBroadcast = (RadioButton)findViewById(R.id.rbStartAppByBroadcast); - - intentTypeSpinnerAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionStartActivity.supportedIntentTypes); - spinnerParameterType.setAdapter(intentTypeSpinnerAdapter); - intentTypeSpinnerAdapter.notifyDataSetChanged(); - - intentPairAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList); - - bSelectApp.setOnClickListener(new OnClickListener() - { - @Override - public void onClick(View v) - { - int targetSdkVersion = getApplicationContext().getApplicationInfo().targetSdkVersion; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && targetSdkVersion >= 30 && !ActivityPermissions.havePermission(Manifest.permission.QUERY_ALL_PACKAGES, ActivityManageActionStartActivity.this))// && shouldShowRequestPermissionRationale(Manifest.permission.QUERY_ALL_PACKAGES)) - { - if(BuildConfig.FLAVOR.equals("googlePlayFlavor")) - { - // This ain't possible anymore. - Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.featureNotInGooglePlayVersion) + Miscellaneous.lineSeparator + Miscellaneous.lineSeparator + getResources().getString(R.string.startActivityInsertManually), ActivityManageActionStartActivity.this).show(); - } - else - requestPermissions(new String[] {Manifest.permission.QUERY_ALL_PACKAGES}, requestCodeForRequestQueryAllPackagesPermission); - } - else - getAppList(); - } - }); - - bAddIntentPair.setOnClickListener(new OnClickListener() - { - @Override - public void onClick(View v) - { - // type;name;value - if(spinnerParameterType.getSelectedItem().toString().length() == 0) - { - Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show(); - return; - } - - if(etParameterName.getText().toString().length() == 0) - { - Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show(); - return; - } - else if(etParameterName.getText().toString().contains(Action.intentPairSeparator)) - { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); - return; - } - else if(etParameterName.getText().toString().contains(";")) - { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); - return; - } - - if(etParameterValue.getText().toString().length() == 0) - { - Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show(); - return; - } - else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator)) - { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); - return; - } - else if(etParameterValue.getText().toString().contains(";")) - { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), ";"), Toast.LENGTH_LONG).show(); - return; - } - - String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString(); - intentPairList.add(param); - - spinnerParameterType.setSelection(0); - etParameterName.setText(""); - etParameterValue.setText(""); - - updateIntentPairList(); - - if(lvIntentPairs.getVisibility() != View.VISIBLE) - lvIntentPairs.setVisibility(View.VISIBLE); - } - }); - - showStartProgramExamples.setOnClickListener(new OnClickListener() - { - @Override - public void onClick(View v) - { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlShowExamples)); - startActivity(browserIntent); - } - }); - - lvIntentPairs.setOnItemLongClickListener(new OnItemLongClickListener() - { - @Override - public boolean onItemLongClick(AdapterView arg0, View arg1, int arg2, long arg3) - { - getIntentPairDialog(arg2).show(); - return false; - } - }); - - bSaveActionStartOtherActivity.setOnClickListener(new OnClickListener() - { - @Override - public void onClick(View v) - { - if(saveAction()) - { - ActivityManageActionStartActivity.this.setResult(RESULT_OK); - finish(); - } - } - }); - - lvIntentPairs.setOnTouchListener(new OnTouchListener() - { - @Override - public boolean onTouch(View v, MotionEvent event) - { - v.getParent().requestDisallowInterceptTouchEvent(true); - return false; - } - }); - - spinnerParameterType.setOnItemSelectedListener(new OnItemSelectedListener() - { - @Override - public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) - { - if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short")) - ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER); - else - ActivityManageActionStartActivity.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT); - } - - @Override - public void onNothingSelected(AdapterView arg0) - { - // TODO Auto-generated method stub - - } - }); - - rbStartAppSelectByActivity.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() - { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) - { - if(isChecked) - bSelectApp.setEnabled(isChecked); - } - }); - - rbStartAppSelectByAction.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() - { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) - { - if(isChecked) - bSelectApp.setEnabled(!isChecked); - } - }); - - Intent i = getIntent(); - if(i.getBooleanExtra("edit", false) == true) - { - edit = true; - loadValuesIntoGui(); - } - } private void loadValuesIntoGui() { diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java b/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java index 8a3d2bb6..9a41e210 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionTriggerUrl.java @@ -47,7 +47,7 @@ public class ActivityManageActionTriggerUrl extends Activity chkTriggerUrlUseAuthentication = (CheckBox)findViewById(R.id.chkTriggerUrlUseAuthentication); lvTriggerUrlPostParameters = (ListView)findViewById(R.id.lvTriggerUrlPostParameters); tlTriggerUrlAuthentication = (TableLayout)findViewById(R.id.tlTriggerUrlAuthentication); - bSaveTriggerUrl = (Button)findViewById(R.id.bSaveTriggerUrl); + bSaveTriggerUrl = (Button)findViewById(R.id.bSaveSpeakText); bSaveTriggerUrl.setOnClickListener(new OnClickListener() { @Override diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionWifi.java b/app/src/main/java/com/jens/automation2/ActivityManageActionWifi.java new file mode 100644 index 00000000..38b948f0 --- /dev/null +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionWifi.java @@ -0,0 +1,63 @@ +package com.jens.automation2; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.RadioButton; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +public class ActivityManageActionWifi extends Activity +{ + CheckBox chkWifiRunAsRoot; + RadioButton rbActionWifiOn, rbActionWifiOff; + Button bActionWifiSave; + TextView tvWifiExplanation1, tvWifiExplanation2; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_action_wifi); + + chkWifiRunAsRoot = (CheckBox)findViewById(R.id.chkWifiRunAsRoot); + rbActionWifiOn = (RadioButton) findViewById(R.id.rbActionWifiOn); + rbActionWifiOff = (RadioButton)findViewById(R.id.rbActionWifiOff); + bActionWifiSave = (Button) findViewById(R.id.bActionWifiSave); + tvWifiExplanation1 = (TextView)findViewById(R.id.tvWifiExplanation1); + tvWifiExplanation2 = (TextView)findViewById(R.id.tvWifiExplanation2); + + Intent input = getIntent(); + if(input.hasExtra(ActivityManageRule.intentNameActionParameter1)) + rbActionWifiOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true)); + + if(input.hasExtra(ActivityManageRule.intentNameActionParameter2)) + chkWifiRunAsRoot.setChecked(Boolean.parseBoolean(input.getStringExtra(ActivityManageRule.intentNameActionParameter2))); + +// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) +// Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android10WifiToggleNotice), ActivityManageActionWifi.this).show(); + + if(getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) + tvWifiExplanation1.setVisibility(View.VISIBLE); + else + tvWifiExplanation1.setVisibility(View.GONE); + + bActionWifiSave.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View view) + { + Intent response = new Intent(); + response.putExtra(ActivityManageRule.intentNameActionParameter1, rbActionWifiOn.isChecked()); + response.putExtra(ActivityManageRule.intentNameActionParameter2, String.valueOf(chkWifiRunAsRoot.isChecked())); + setResult(RESULT_OK, response); + finish(); + } + }); + } +} diff --git a/app/src/main/java/com/jens/automation2/ActivityManageRule.java b/app/src/main/java/com/jens/automation2/ActivityManageRule.java index 05c41cae..aa4cd1ae 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageRule.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageRule.java @@ -123,7 +123,13 @@ public class ActivityManageRule extends Activity final static int requestCodeTriggerBroadcastReceivedEdit = 810; final static int requestCodeActionSendBroadcastAdd = 811; final static int requestCodeActionSendBroadcastEdit = 812; - + final static int requestCodeActionRunExecutableAdd = 813; + final static int requestCodeActionRunExecutableEdit = 814; + final static int requestCodeActionSetWifiAdd = 815; + final static int requestCodeActionSetWifiEdit = 816; + final static int requestCodeTriggerTetheringAdd = 817; + final static int requestCodeTriggerTetheringEdit = 818; + public static ActivityManageRule getInstance() { if(instance == null) @@ -308,6 +314,11 @@ public class ActivityManageRule extends Activity broadcastEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2()); startActivityForResult(broadcastEditor, requestCodeTriggerBroadcastReceivedEdit); break; + case tethering: + Intent tetheringEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTethering.class); + tetheringEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter()); + startActivityForResult(tetheringEditor, requestCodeTriggerTetheringEdit); + break; default: break; } @@ -382,6 +393,18 @@ public class ActivityManageRule extends Activity activityEditSendBroadcastIntent.putExtra(intentNameActionParameter2, a.getParameter2()); startActivityForResult(activityEditSendBroadcastIntent, requestCodeActionSendBroadcastEdit); break; + case runExecutable: + Intent activityEditRunExecutableIntent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class); + activityEditRunExecutableIntent.putExtra(intentNameActionParameter1, a.getParameter1()); + activityEditRunExecutableIntent.putExtra(intentNameActionParameter2, a.getParameter2()); + startActivityForResult(activityEditRunExecutableIntent, requestCodeActionRunExecutableEdit); + break; + case setWifi: + Intent activityEditSetWifiIntent = new Intent(ActivityManageRule.this, ActivityManageActionWifi.class); + activityEditSetWifiIntent.putExtra(intentNameActionParameter1, a.getParameter1()); + activityEditSetWifiIntent.putExtra(intentNameActionParameter2, a.getParameter2()); + startActivityForResult(activityEditSetWifiIntent, requestCodeActionSetWifiEdit); + break; case controlMediaPlayback: Intent activityEditControlMediaIntent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class); activityEditControlMediaIntent.putExtra(ActivityManageRule.intentNameActionParameter2, a.getParameter2()); @@ -524,7 +547,7 @@ public class ActivityManageRule extends Activity else if(types[i].toString().equals(Trigger_Enum.roaming.toString())) items.add(new Item(typesLong[i].toString(), R.drawable.roaming)); else if(types[i].toString().equals(Trigger_Enum.broadcastReceived.toString())) - items.add(new Item(typesLong[i].toString(), R.drawable.satellite)); + items.add(new Item(typesLong[i].toString(), R.drawable.megaphone)); else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString())) { if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, "android.permission.SEND_SMS")) @@ -552,6 +575,8 @@ public class ActivityManageRule extends Activity items.add(new Item(typesLong[i].toString(), R.drawable.alarm)); else if(types[i].toString().equals(Trigger_Enum.serviceStarts.toString())) items.add(new Item(typesLong[i].toString(), R.drawable.alarm)); + else if(types[i].toString().equals(Trigger_Enum.tethering.toString())) + items.add(new Item(typesLong[i].toString(), R.drawable.router)); else items.add(new Item(typesLong[i].toString(), R.drawable.placeholder)); } @@ -751,6 +776,13 @@ public class ActivityManageRule extends Activity startActivityForResult(broadcastTriggerEditor, requestCodeTriggerBroadcastReceivedAdd); return; } + else if(triggerType == Trigger_Enum.tethering) + { + newTrigger.setTriggerType(Trigger_Enum.tethering); + Intent tetheringTriggerEditor = new Intent(myContext, ActivityManageTriggerTethering.class); + startActivityForResult(tetheringTriggerEditor, requestCodeTriggerTetheringAdd); + return; + } else getTriggerParameterDialog(context, booleanChoices).show(); @@ -1499,6 +1531,17 @@ public class ActivityManageRule extends Activity this.refreshActionList(); } } + else if(requestCode == requestCodeActionRunExecutableAdd) + { + if(resultCode == RESULT_OK) + { + newAction.setParentRule(ruleToEdit); + newAction.setParameter1(data.getBooleanExtra(intentNameActionParameter1, false)); + newAction.setParameter2(data.getStringExtra(intentNameActionParameter2)); + ruleToEdit.getActionSet().add(newAction); + this.refreshActionList(); + } + } else if(requestCode == requestCodeActionControlMediaAdd) { if(resultCode == RESULT_OK) @@ -1509,6 +1552,17 @@ public class ActivityManageRule extends Activity this.refreshActionList(); } } + else if(requestCode == requestCodeActionSetWifiAdd) + { + if(resultCode == RESULT_OK) + { + newAction.setParentRule(ruleToEdit); + newAction.setParameter1(data.getBooleanExtra(ActivityManageRule.intentNameActionParameter1, true)); + newAction.setParameter2(data.getStringExtra(ActivityManageRule.intentNameActionParameter2)); + ruleToEdit.getActionSet().add(newAction); + this.refreshActionList(); + } + } else if(requestCode == requestCodeActionCreateNotificationAdd) { if(resultCode == RESULT_OK) @@ -1557,6 +1611,36 @@ public class ActivityManageRule extends Activity this.refreshActionList(); } } + else if(requestCode == requestCodeActionRunExecutableEdit) + { + if(resultCode == RESULT_OK) + { + ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit); + + if(data.hasExtra(intentNameActionParameter1) && data.hasExtra(intentNameActionParameter2)) + { + ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, false)); + ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2)); + } + + this.refreshActionList(); + } + } + else if(requestCode == requestCodeActionSetWifiEdit) + { + if(resultCode == RESULT_OK) + { + ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit); + + if(data.hasExtra(intentNameActionParameter1) && data.hasExtra(intentNameActionParameter2)) + { + ruleToEdit.getActionSet().get(editIndex).setParameter1(data.getBooleanExtra(intentNameActionParameter1, false)); + ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2)); + } + + this.refreshActionList(); + } + } else if(requestCode == requestCodeActionControlMediaEdit) { if(resultCode == RESULT_OK) @@ -1714,6 +1798,28 @@ public class ActivityManageRule extends Activity this.refreshTriggerList(); } } + else if(requestCode == requestCodeTriggerTetheringAdd) + { + if(resultCode == RESULT_OK) + { + newTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true)); + newTrigger.setParentRule(ruleToEdit); + ruleToEdit.getTriggerSet().add(newTrigger); + this.refreshTriggerList(); + } + } + else if(requestCode == requestCodeTriggerTetheringEdit) + { + if(resultCode == RESULT_OK) + { + Trigger editedTrigger = new Trigger(); + editedTrigger.setTriggerType(Trigger_Enum.tethering); + editedTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true)); + editedTrigger.setParentRule(ruleToEdit); + ruleToEdit.getTriggerSet().set(editIndex, editedTrigger); + this.refreshTriggerList(); + } + } } protected AlertDialog getActionTypeDialog() @@ -1768,7 +1874,9 @@ public class ActivityManageRule extends Activity else if(types[i].toString().equals(Action_Enum.closeNotification.toString())) items.add(new Item(typesLong[i].toString(), R.drawable.notification)); else if(types[i].toString().equals(Action_Enum.sendBroadcast.toString())) - items.add(new Item(typesLong[i].toString(), R.drawable.satellite)); + items.add(new Item(typesLong[i].toString(), R.drawable.megaphone)); + else if(types[i].toString().equals(Action_Enum.runExecutable.toString())) + items.add(new Item(typesLong[i].toString(), R.drawable.script)); else if(types[i].toString().equals(Action_Enum.sendTextMessage.toString())) { // if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageSpecificRule.this, "android.permission.SEND_SMS") && !Miscellaneous.isGooglePlayInstalled(ActivityManageSpecificRule.this)) @@ -1818,10 +1926,8 @@ public class ActivityManageRule extends Activity else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setWifi.toString())) { newAction.setAction(Action_Enum.setWifi); - getActionParameter1Dialog(ActivityManageRule.this).show(); - - if(context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) - Miscellaneous.messageBox(context.getResources().getString(R.string.app_name), context.getResources().getString(R.string.android10WifiToggleNotice), context).show(); + Intent editSetWifiIntent = new Intent(context, ActivityManageActionWifi.class); + startActivityForResult(editSetWifiIntent, requestCodeActionSetWifiAdd); } else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setBluetooth.toString())) { @@ -1937,6 +2043,12 @@ public class ActivityManageRule extends Activity Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionSendBroadcast.class); startActivityForResult(intent, requestCodeActionSendBroadcastAdd); } + else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.runExecutable.toString())) + { + newAction.setAction(Action_Enum.runExecutable); + Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionRunExecutable.class); + startActivityForResult(intent, requestCodeActionRunExecutableAdd); + } else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString())) { newAction.setAction(Action_Enum.controlMediaPlayback); diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerTethering.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerTethering.java new file mode 100644 index 00000000..15ad0be0 --- /dev/null +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerTethering.java @@ -0,0 +1,46 @@ +package com.jens.automation2; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.RadioButton; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +public class ActivityManageTriggerTethering extends Activity +{ + RadioButton rbTetheringOn, rTetheringOff; + Button bTriggerTetheringSave; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_trigger_tethering); + + rbTetheringOn = (RadioButton) findViewById(R.id.rbTetheringOn); + rTetheringOff = (RadioButton)findViewById(R.id.rTetheringOff); + bTriggerTetheringSave = (Button) findViewById(R.id.bTriggerTetheringSave); + + Intent input = getIntent(); + if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1)) + rbTetheringOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true)); + + bTriggerTetheringSave.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View view) + { + Intent response = new Intent(); + response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbTetheringOn.isChecked()); + setResult(RESULT_OK, response); + finish(); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityPermissions.java b/app/src/main/java/com/jens/automation2/ActivityPermissions.java index 62a47c56..34d04caf 100644 --- a/app/src/main/java/com/jens/automation2/ActivityPermissions.java +++ b/app/src/main/java/com/jens/automation2/ActivityPermissions.java @@ -250,7 +250,7 @@ public class ActivityPermissions extends Activity } else if(s.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || s.equalsIgnoreCase(permissionNameGoogleActivityDetection)) { - if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor")) + if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid)) if (!havePermission(s, context)) return true; } @@ -381,7 +381,7 @@ public class ActivityPermissions extends Activity } else if (singlePermission.equalsIgnoreCase(Manifest.permission.ACTIVITY_RECOGNITION) || singlePermission.equalsIgnoreCase(permissionNameGoogleActivityDetection)) { - if (!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor")) + if (!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid)) addToArrayListUnique(singlePermission, requiredPermissions); } else diff --git a/app/src/main/java/com/jens/automation2/ActivitySettings.java b/app/src/main/java/com/jens/automation2/ActivitySettings.java index a8e81a3c..6c69ce73 100644 --- a/app/src/main/java/com/jens/automation2/ActivitySettings.java +++ b/app/src/main/java/com/jens/automation2/ActivitySettings.java @@ -18,7 +18,7 @@ public class ActivitySettings extends PreferenceActivity super.onCreate(savedInstanceState); addPreferencesFromResource(layout.activity_settings); - if(BuildConfig.FLAVOR.equals("apkFlavor")) + if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_apk)) { chkPrefUpdateCheck = (CheckBoxPreference) findPreference("automaticUpdateCheck"); chkPrefUpdateCheck.setEnabled(true); diff --git a/app/src/main/java/com/jens/automation2/AutomationService.java b/app/src/main/java/com/jens/automation2/AutomationService.java index 98f31063..2d5fc7fd 100644 --- a/app/src/main/java/com/jens/automation2/AutomationService.java +++ b/app/src/main/java/com/jens/automation2/AutomationService.java @@ -43,6 +43,10 @@ public class AutomationService extends Service implements OnInitListener protected final static int notificationIdRestrictions = 1005; protected final static int notificationIdLocationRestriction = 1006; + public static final String flavor_name_apk = "apkFlavor"; + public static final String flavor_name_fdroid = "fdroidFlavor"; + public static final String flavor_name_googleplay = "googlePlayFlavor"; + final static String NOTIFICATION_CHANNEL_ID_SERVICE = "com.jens.automation2_service"; final static String NOTIFICATION_CHANNEL_NAME_SERVICE = "Service notification"; diff --git a/app/src/main/java/com/jens/automation2/Miscellaneous.java b/app/src/main/java/com/jens/automation2/Miscellaneous.java index c55297b8..d32272d8 100644 --- a/app/src/main/java/com/jens/automation2/Miscellaneous.java +++ b/app/src/main/java/com/jens/automation2/Miscellaneous.java @@ -738,8 +738,8 @@ public class Miscellaneous extends Service * * @return true if the device is rooted, false otherwise. */ - public static boolean isPhoneRooted() - { + public static boolean isPhoneRooted() + { // if(true) // return true; @@ -747,30 +747,30 @@ public class Miscellaneous extends Service String buildTags = Build.TAGS; if (buildTags != null && buildTags.contains("test-keys")) { - return true; + return true; } // check if /system/app/Superuser.apk is present - try - { - File file = new File("/system/app/Superuser.apk"); - if (file.exists()) - { - return true; - } - } - catch (Exception e1) - { + try + { + File file = new File("/system/app/Superuser.apk"); + if (file.exists()) + { + return true; + } + } + catch (Exception e1) + { // ignore - } + } // try executing commands - return canExecuteCommand("/system/xbin/which su") + return canExecuteCommand("/system/xbin/which su") || canExecuteCommand("/system/bin/which su") || canExecuteCommand("which su"); - } + } // executes a command on the system private static boolean canExecuteCommand(String command) @@ -798,9 +798,9 @@ public class Miscellaneous extends Service * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to * aid testing on a local box, not for use on production. */ - private static void disableSSLCertificateChecking() - { - try + private static void disableSSLCertificateChecking() + { + try { SSLSocketFactory ssf = null; @@ -1620,7 +1620,7 @@ public class Miscellaneous extends Service { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - if (BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor")) + if (BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay)) { if(checkExistingRules) { diff --git a/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java b/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java index 4d759539..23a1f77e 100644 --- a/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java +++ b/app/src/main/java/com/jens/automation2/ReceiverCoordinator.java @@ -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.TetheringReceiver; import com.jens.automation2.receivers.TimeZoneListener; import androidx.annotation.RequiresApi; @@ -59,7 +60,8 @@ public class ReceiverCoordinator ProcessListener.class, MediaPlayerListener.class, ScreenStateReceiver.class, - TimeZoneListener.class + TimeZoneListener.class, + TetheringReceiver.class }; } catch (ClassNotFoundException e) @@ -77,7 +79,8 @@ public class ReceiverCoordinator PhoneStatusListener.class, ProcessListener.class, ScreenStateReceiver.class, - TimeZoneListener.class + TimeZoneListener.class, + TetheringReceiver.class }; } } @@ -176,6 +179,9 @@ public class ReceiverCoordinator if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.deviceOrientation)) DeviceOrientationListener.getInstance().startListener(AutomationService.getInstance()); + if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering)) + TetheringReceiver.getInstance().startListener(AutomationService.getInstance()); + try { Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath); @@ -216,6 +222,7 @@ public class ReceiverCoordinator ProcessListener.stopProcessListener(AutomationService.getInstance()); MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance()); DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance()); + TetheringReceiver.getInstance().stopListener(AutomationService.getInstance()); try { @@ -318,7 +325,7 @@ public class ReceiverCoordinator MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance()); } - if(!BuildConfig.FLAVOR.equalsIgnoreCase("fdroidFlavor")) + if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_fdroid)) { if (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.activityDetection)) { @@ -415,6 +422,24 @@ public class ReceiverCoordinator } } + if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering)) + { + if(!TetheringReceiver.getInstance().isListenerRunning()) + { + Miscellaneous.logEvent("i", "TetheringReceiver", "Starting TetheringReceiver because used in a new/changed rule.", 4); +// if(DevicePositionListener.getInstance().haveAllPermission()) + TetheringReceiver.getInstance().startListener(AutomationService.getInstance()); + } + } + else + { + if(TetheringReceiver.getInstance().isListenerRunning()) + { + Miscellaneous.logEvent("i", "TetheringReceiver", "Shutting down TetheringReceiver because not used in any rule.", 4); + TetheringReceiver.getInstance().stopListener(AutomationService.getInstance()); + } + } + AutomationService.updateNotification(); } } diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index ae3e0919..ba51232b 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -24,10 +24,10 @@ import com.jens.automation2.receivers.NotificationListener; import com.jens.automation2.receivers.PhoneStatusListener; import com.jens.automation2.receivers.ProcessListener; import com.jens.automation2.receivers.ScreenStateReceiver; +import com.jens.automation2.receivers.TetheringReceiver; import org.apache.commons.lang3.StringUtils; -import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -59,6 +59,7 @@ public class Trigger deviceStarts, serviceStarts, broadcastReceived, + tethering, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy public String getFullName(Context context) @@ -113,6 +114,8 @@ public class Trigger return context.getResources().getString(R.string.serviceStarts); case broadcastReceived: return context.getResources().getString(R.string.broadcastReceivedTitle); + case tethering: + return context.getResources().getString(R.string.tetheringState); default: return "Unknown"; } @@ -228,6 +231,10 @@ public class Trigger if(!checkBroadcastReceived()) result = false; break; + case tethering: + if(!checkTetheringActive()) + result = false; + break; default: break; } @@ -919,6 +926,11 @@ public class Trigger return true; } + boolean checkTetheringActive() + { + return TetheringReceiver.isTetheringActive() == triggerParameter; + } + public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution) { /* @@ -1636,6 +1648,12 @@ public class Trigger returnString.append(": " + triggerParameter2); break; + case tethering: + if(triggerParameter) + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringActive)); + else + returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringNotActive)); + break; default: returnString.append("error"); break; diff --git a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java index 5f4d68a3..79e93d9c 100644 --- a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java @@ -26,7 +26,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver public static Boolean wasConnected = false; protected static String lastWifiSsid = ""; public static boolean lastConnectedState = false; - protected static boolean mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = true; + protected static boolean mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true; protected static WifiBroadcastReceiver wifiBrInstance; protected static IntentFilter wifiListenerIntentFilter; protected static boolean wifiListenerActive=false; @@ -52,7 +52,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver public static boolean mayCellLocationReceiverBeActivated() { - return mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi; + return mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView; } @Override @@ -63,18 +63,12 @@ public class WifiBroadcastReceiver extends BroadcastReceiver // int state = -1; NetworkInfo myWifi = null; - // if(intent.getAction().equals(WifiManager.RSSI_CHANGED_ACTION)) //gefeuert bei Verbindung - // { - // Miscellaneous.logEvent("i", "WifiReceiver", "RSSI_CHANGED_ACTION: " + String.valueOf(intent.getIntExtra(WifiManager.RSSI_CHANGED_ACTION, -1))); - // } - // else if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) //gefeuert bei Trennung { // state = intent.getIntExtra(WifiManager.NETWORK_STATE_CHANGED_ACTION, -1); // Miscellaneous.logEvent("i", "WifiReceiver", "NETWORK_STATE_CHANGED_ACTION: " + String.valueOf(state)); myWifi = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); } - WifiManager myWifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); // ConnectivityManager connManager = (ConnectivityManager)context.getSystemService(context.CONNECTIVITY_SERVICE); @@ -95,8 +89,14 @@ public class WifiBroadcastReceiver extends BroadcastReceiver if(Settings.useWifiForPositioning && PointOfInterest.reachedPoiWithActivateWifiRule()) // Poi has wifi { Miscellaneous.logEvent("i", "WifiReceiver", context.getResources().getString(R.string.poiHasWifiStoppingCellLocationListener), 2); - mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = false; + mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = false; CellLocationChangedReceiver.stopCellLocationChangedReceiver(); + + /* + TODO: Every time the screen is turned on, we receiver a "wifi has been connected"-event. + This is technically wrong and not really any changed to when the screen was off. It has + to be filtered. + */ } else { @@ -110,7 +110,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver { wasConnected = true; Miscellaneous.logEvent("i", "WifiReceiver", "WifiReceiver just activated. Wifi already connected. Stopping CellLocationReceiver", 3); - mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = false; + mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = false; CellLocationChangedReceiver.stopCellLocationChangedReceiver(); SensorActivity.stopAccelerometerTimer(); String ssid = myWifiManager.getConnectionInfo().getSSID(); @@ -126,7 +126,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver { wasConnected = false; Miscellaneous.logEvent("i", "WifiReceiver", String.format(context.getResources().getString(R.string.disconnectedFromWifi), getLastWifiSsid()) + " Switching to CellLocationChangedReceiver.", 3); - mayCellLocationChangedReceiverBeActivatedFromWifiPointOfWifi = true; + mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true; CellLocationChangedReceiver.startCellLocationChangedReceiver(); lastConnectedState = false; findRules(AutomationService.getInstance()); diff --git a/app/src/main/java/com/jens/automation2/receivers/BroadcastListener.java b/app/src/main/java/com/jens/automation2/receivers/BroadcastListener.java index e4102b2d..204a3b5d 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BroadcastListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/BroadcastListener.java @@ -3,8 +3,10 @@ package com.jens.automation2.receivers; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Build; import android.os.Bundle; import android.util.Log; +import android.widget.Toast; import com.jens.automation2.ActivityPermissions; import com.jens.automation2.AutomationService; @@ -53,8 +55,6 @@ public class BroadcastListener extends android.content.BroadcastReceiver impleme for(String key : intent.getExtras().keySet()) { Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4); -// Object ob = intent.getExtras().get(key); -// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4); } ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.broadcastReceived); diff --git a/app/src/main/java/com/jens/automation2/receivers/TetheringReceiver.java b/app/src/main/java/com/jens/automation2/receivers/TetheringReceiver.java new file mode 100644 index 00000000..7f2b8461 --- /dev/null +++ b/app/src/main/java/com/jens/automation2/receivers/TetheringReceiver.java @@ -0,0 +1,130 @@ +package com.jens.automation2.receivers; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.util.Log; + +import com.jens.automation2.AutomationService; +import com.jens.automation2.Miscellaneous; +import com.jens.automation2.Rule; +import com.jens.automation2.Trigger; + +import java.util.ArrayList; + +public class TetheringReceiver extends android.content.BroadcastReceiver implements AutomationListenerInterface +{ + public static AutomationService automationServiceRef = null; + private static boolean receiverActive = false; + private static TetheringReceiver receiverInstance = null; + private static IntentFilter intentFilter = null; + + private static boolean tetheringActive = false; + + public static TetheringReceiver getInstance() + { + if(receiverInstance == null) + receiverInstance = new TetheringReceiver(); + + return receiverInstance; + } + + public static boolean isTetheringActive() + { + return tetheringActive; + } + + @Override + public void onReceive(Context context, Intent intent) + { + for(String key : intent.getExtras().keySet()) + { +// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4); + Object ob = intent.getExtras().get(key); + + String target = null; + + if(Build.VERSION.SDK_INT >= 26) + target = "tetherArray"; + else + target = "activeArray"; + + if(key.equals(target) && ob instanceof ArrayList) + { + if(((ArrayList)ob).size() > 0) + tetheringActive = true; + else + tetheringActive = false; + } + +// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4); + } + + ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.tethering); + for(int i=0; i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +