From a6e10d09c379c9d11f43b020857882f86ec41e86 Mon Sep 17 00:00:00 2001 From: Jens Date: Sun, 19 Oct 2025 23:32:34 +0200 Subject: [PATCH] Forum added to contact options --- app/src/apkFlavor/AndroidManifest.xml | 2 +- app/src/fdroidFlavor/AndroidManifest.xml | 2 +- app/src/googlePlayFlavor/AndroidManifest.xml | 2 +- .../java/com/jens/automation2/Actions.java | 4051 +++++++++-------- .../jens/automation2/ActivityMainScreen.java | 7 +- .../jens/automation2/AutomationService.java | 16 +- .../main/res/layout/main_overview_layout.xml | 3 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- .../metadata/android/en-US/changelogs/145.txt | 1 + 17 files changed, 2060 insertions(+), 2042 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/145.txt diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml index 9bd5452..9f1a95f 100644 --- a/app/src/apkFlavor/AndroidManifest.xml +++ b/app/src/apkFlavor/AndroidManifest.xml @@ -79,7 +79,7 @@ - + --> - + --> - + = Build.VERSION_CODES.KITKAT) - { - String[] params = action.getParameter2().split(Action.actionParameter2Split); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + { + String[] params = action.getParameter2().split(Action.actionParameter2Split); - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText = ""; - String method = ActivityManageActionCloseNotification.dismissRegularString; + String myApp = params[0]; + String myTitleDir = params[1]; + String requiredTitle = params[2]; + String myTextDir = params[3]; + String requiredText = ""; + String method = ActivityManageActionCloseNotification.dismissRegularString; - if(params.length >= 5) - requiredText = params[4]; + if (params.length >= 5) + requiredText = params[4]; - if(params.length >= 6 && !params[5].equals(ActivityManageActionCloseNotification.dismissRegularString)) - method = params[5]; + if (params.length >= 6 && !params[5].equals(ActivityManageActionCloseNotification.dismissRegularString)) + method = params[5]; - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn); + for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) + { + NotificationListener.SimpleNotification sn = NotificationListener.convertNotificationToSimpleNotification(true, sbn); - Miscellaneous.logEvent("i", "NotificationCloseCheck", "Checking if this notification should be closed in the context of rule " + action.getParentRule().getName() + ": "+ sn.toString(), 5); + Miscellaneous.logEvent("i", "NotificationCloseCheck", "Checking if this notification should be closed in the context of rule " + action.getParentRule().getName() + ": " + sn.toString(), 5); - if (!myApp.equals(Trigger.anyAppString)) - { - if (!myApp.equalsIgnoreCase(sn.getApp())) - { - Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { + if (!myApp.equals(Trigger.anyAppString)) + { + if (!myApp.equalsIgnoreCase(sn.getApp())) + { + Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification app name does not match rule.", 5); + continue; + } + } + else + { /* Notifications from Automation are disregarded to avoid infinite loops. */ - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - continue; - } - } + if (myApp.equals(BuildConfig.APPLICATION_ID)) + { + continue; + } + } /* If there are multiple notifications ("stacked") title or text might be null: https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications */ - // T I T L E - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle())) - { - Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification title does not match rule.", 5); - continue; - } - } + // T I T L E + if (!StringUtils.isEmpty(requiredTitle)) + { + if (!Miscellaneous.compare(myTitleDir, requiredTitle, sn.getTitle())) + { + Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification title does not match rule.", 5); + continue; + } + } - // T E X T - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText())) - { - Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification text does not match rule.", 5); - continue; - } - } + // T E X T + if (!StringUtils.isEmpty(requiredText)) + { + if (!Miscellaneous.compare(myTextDir, requiredText, sn.getText())) + { + Miscellaneous.logEvent("i", "NotificationCloseCheck", "Notification text does not match rule.", 5); + continue; + } + } - Miscellaneous.logEvent("i", "NotificationCloseCheck", "All criteria matches. Closing notification: " + sbn.getNotification().toString(), 3); - if(NotificationListener.getInstance() != null) - { - if(method == ActivityManageActionCloseNotification.dismissRegularString) - NotificationListener.getInstance().dismissNotification(sbn); - else - NotificationListener.getInstance().clickNotificationButton(sbn, method); - } - else - Miscellaneous.logEvent("i", "NotificationCloseCheck", "NotificationListener instance is null. Can\'t close notification.", 3); - } - } + Miscellaneous.logEvent("i", "NotificationCloseCheck", "All criteria matches. Closing notification: " + sbn.getNotification().toString(), 3); + if (NotificationListener.getInstance() != null) + { + if (method == ActivityManageActionCloseNotification.dismissRegularString) + NotificationListener.getInstance().dismissNotification(sbn); + else + NotificationListener.getInstance().clickNotificationButton(sbn, method); + } + else + Miscellaneous.logEvent("i", "NotificationCloseCheck", "NotificationListener instance is null. Can\'t close notification.", 3); + } + } // } - } + } public static void sendBroadcast(Context context, String action) { - Miscellaneous.logEvent("i", "sendBroadcast", "Sending broadcast with action " + action, 5); - Intent broadcastIntent = new Intent(); + Miscellaneous.logEvent("i", "sendBroadcast", "Sending broadcast with action " + action, 5); + Intent broadcastIntent = new Intent(); - if(action.contains(Action.actionParameter2Split)) - { - String[] parts = action.split(Action.actionParameter2Split); - broadcastIntent.setAction(parts[0]); + 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); + String[] intentParts = parts[1].split(";"); + broadcastIntent = packParametersIntoIntent(broadcastIntent, intentParts, 0); + } + else + broadcastIntent.setAction(action); - context.sendBroadcast(broadcastIntent); + context.sendBroadcast(broadcastIntent); } - public static void setVariable(String parameter2) - { - String[] parts = parameter2.split(Action.actionParameter2Split); + public static void setVariable(String parameter2) + { + String[] parts = parameter2.split(Action.actionParameter2Split); - if(AutomationService.isMyServiceRunning(Miscellaneous.getAnyContext())) - { - Map map = AutomationService.getInstance().getVariableMap(); + if (AutomationService.isMyServiceRunning(Miscellaneous.getAnyContext())) + { + Map map = AutomationService.getInstance().getVariableMap(); - if(parts.length > 1) - { - try - { - map.put(parts[0], Miscellaneous.replaceVariablesInText(parts[1], Miscellaneous.getAnyContext())); - } - catch (Exception e) - { - map.put(parts[0], parts[1]); - } - } - else - map.remove(parts[0]); - } + if (parts.length > 1) + { + try + { + map.put(parts[0], Miscellaneous.replaceVariablesInText(parts[1], Miscellaneous.getAnyContext())); + } + catch (Exception e) + { + map.put(parts[0], parts[1]); + } + } + else + map.remove(parts[0]); + } - Miscellaneous.logEvent("i", "Variable", "Checking for applicable rules after variable has been set or deleted.", 2); - List ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.checkVariable); - for(int i=0; i ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.checkVariable); + for (int i = 0; i < ruleCandidates.size(); i++) + { + if (ruleCandidates.get(i).haveEnoughPermissions() && ruleCandidates.get(i).getsGreenLight(AutomationService.getInstance())) + { + Miscellaneous.logEvent("i", "Variable", "Rule " + ruleCandidates.get(i).getName() + " applies after variable has been set or deleted.", 2); + ruleCandidates.get(i).activate(AutomationService.getInstance(), false); + } + } + Miscellaneous.logEvent("i", "Variable", "Done checking for applicable rules after variable has been set or deleted.", 2); - } + } - public static class WifiStuff - { - public static Boolean setWifi(Context context, Boolean desiredState, String parameter2, boolean toggleActionIfPossible) - { - boolean forceUseRoot = false; + public static class WifiStuff + { + public static Boolean setWifi(Context context, Boolean desiredState, String parameter2, boolean toggleActionIfPossible) + { + boolean forceUseRoot = false; - try - { - forceUseRoot = Boolean.parseBoolean(parameter2); - } - catch(Exception e) - { + try + { + forceUseRoot = Boolean.parseBoolean(parameter2); + } + catch (Exception e) + { - } + } - if(context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q || forceUseRoot) - return setWifiWithRoot(context, desiredState, toggleActionIfPossible); - else - return setWifiOldFashioned(context, desiredState, toggleActionIfPossible); - } + if (context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q || forceUseRoot) + return setWifiWithRoot(context, desiredState, toggleActionIfPossible); + else + return setWifiOldFashioned(context, desiredState, toggleActionIfPossible); + } - public static Boolean setWifiWithRoot(Context context, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState) + ", but with root permissions.", 4); + public static Boolean setWifiWithRoot(Context context, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState) + ", but with root permissions.", 4); - String command = null; + String command = null; String desiredStateString; - if(desiredState) - desiredStateString = "enable"; - else - desiredStateString = "disable"; + if (desiredState) + desiredStateString = "enable"; + else + desiredStateString = "disable"; - try - { - command = "svc wifi " + desiredStateString; - Miscellaneous.logEvent("i", "setWifiWithRoot()", "Running command as root: " + command.toString(), 5); - return executeCommandViaSu(new String[]{command}); - } - catch (Exception e) - { - // Oops! Something went wrong, so we throw the exception here. - throw e; - } - } + try + { + command = "svc wifi " + desiredStateString; + Miscellaneous.logEvent("i", "setWifiWithRoot()", "Running command as root: " + command.toString(), 5); + return executeCommandViaSu(new String[]{command}); + } + catch (Exception e) + { + // Oops! Something went wrong, so we throw the exception here. + throw e; + } + } - public static Boolean setWifiOldFashioned(Context context, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState), 4); + public static Boolean setWifiOldFashioned(Context context, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "Wifi", "Changing wifi to " + String.valueOf(desiredState), 4); - try - { - if (desiredState && Settings.useWifiForPositioning) - WifiBroadcastReceiver.startWifiReceiver(automationServerRef.getLocationProvider()); - } - catch(Exception e) - { - Miscellaneous.logEvent("w", "setWifiOldFashioned()", Log.getStackTraceString(e), 4); - } + try + { + if (desiredState && Settings.useWifiForPositioning) + WifiBroadcastReceiver.startWifiReceiver(automationServerRef.getLocationProvider()); + } + catch (Exception e) + { + Miscellaneous.logEvent("w", "setWifiOldFashioned()", Log.getStackTraceString(e), 4); + } - WifiManager myWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiManager myWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - // toggle - if (toggleActionIfPossible) - { - Toast.makeText(context, context.getResources().getString(R.string.toggling) + " " + context.getResources().getString(R.string.wifi), Toast.LENGTH_LONG).show(); - desiredState = !myWifi.isWifiEnabled(); - } + // toggle + if (toggleActionIfPossible) + { + Toast.makeText(context, context.getResources().getString(R.string.toggling) + " " + context.getResources().getString(R.string.wifi), Toast.LENGTH_LONG).show(); + desiredState = !myWifi.isWifiEnabled(); + } - // Only perform action if necessary - if ((!myWifi.isWifiEnabled() && desiredState) | (myWifi.isWifiEnabled() && !desiredState)) - { - String wifiString = ""; + // Only perform action if necessary + if ((!myWifi.isWifiEnabled() && desiredState) | (myWifi.isWifiEnabled() && !desiredState)) + { + String wifiString = ""; - if (desiredState) - { - wifiString = context.getResources().getString(R.string.activating) + " " + context.getResources().getString(R.string.wifi); - } - else - { - wifiString = context.getResources().getString(R.string.deactivating) + " " + context.getResources().getString(R.string.wifi); - } + if (desiredState) + { + wifiString = context.getResources().getString(R.string.activating) + " " + context.getResources().getString(R.string.wifi); + } + else + { + wifiString = context.getResources().getString(R.string.deactivating) + " " + context.getResources().getString(R.string.wifi); + } - Toast.makeText(context, wifiString, Toast.LENGTH_LONG).show(); + Toast.makeText(context, wifiString, Toast.LENGTH_LONG).show(); - boolean returnValue = myWifi.setWifiEnabled(desiredState); - if (!returnValue) - Miscellaneous.logEvent("i", "Wifi", "Error changing Wifi to " + String.valueOf(desiredState), 2); - else - Miscellaneous.logEvent("i", "Wifi", "Wifi changed to " + String.valueOf(desiredState), 2); + boolean returnValue = myWifi.setWifiEnabled(desiredState); + if (!returnValue) + Miscellaneous.logEvent("i", "Wifi", "Error changing Wifi to " + String.valueOf(desiredState), 2); + else + Miscellaneous.logEvent("i", "Wifi", "Wifi changed to " + String.valueOf(desiredState), 2); - return returnValue; - } + return returnValue; + } - return true; - } - } + return true; + } + } - public static void setDisplayRotation(Context myContext, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "ScreenRotation", "Changing ScreenRotation to " + String.valueOf(desiredState), 4); - try - { - if (toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.toggling), 2); - boolean currentStatus = android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0; - if (currentStatus) - desiredState = !currentStatus; - } + public static void setDisplayRotation(Context myContext, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "ScreenRotation", "Changing ScreenRotation to " + String.valueOf(desiredState), 4); + try + { + if (toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.toggling), 2); + boolean currentStatus = android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0; + if (currentStatus) + desiredState = !currentStatus; + } - if (desiredState) - { - if (android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0) - { - android.provider.Settings.System.putInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 1); - Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationEnabled), 2); - } - else - Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyEnabled), 2); - } - else - { - if (android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 1) - { - android.provider.Settings.System.putInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0); - Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationDisabled), 2); - } - else - Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyDisabled), 2); - } - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "setScreenRotation", myContext.getResources().getString(R.string.errorChangingScreenRotation) + ": " + Log.getStackTraceString(e), 2); - } - } + if (desiredState) + { + if (android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0) + { + android.provider.Settings.System.putInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 1); + Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationEnabled), 2); + } + else + Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyEnabled), 2); + } + else + { + if (android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 1) + { + android.provider.Settings.System.putInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0); + Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationDisabled), 2); + } + else + Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyDisabled), 2); + } + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "setScreenRotation", myContext.getResources().getString(R.string.errorChangingScreenRotation) + ": " + Log.getStackTraceString(e), 2); + } + } - private static boolean isWifiApEnabled(Context context) - { - WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - boolean currentlyEnabled = false; + private static boolean isWifiApEnabled(Context context) + { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + boolean currentlyEnabled = false; - Method[] methods = wifiManager.getClass().getDeclaredMethods(); - for (Method method : methods) - { - if (method.getName().equals("isWifiApEnabled")) - { - try - { - Object returnObject = method.invoke(wifiManager); - currentlyEnabled = Boolean.valueOf(returnObject.toString()); + Method[] methods = wifiManager.getClass().getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals("isWifiApEnabled")) + { + try + { + Object returnObject = method.invoke(wifiManager); + currentlyEnabled = Boolean.valueOf(returnObject.toString()); - if (currentlyEnabled) - Miscellaneous.logEvent("i", "isWifiApEnabled", "true", 5); - else - Miscellaneous.logEvent("i", "isWifiApEnabled", "false", 5); - } - catch (Exception e) - { - Miscellaneous.logEvent("i", "isWifiApEnabled", context.getResources().getString(R.string.errorDeterminingWifiApState) + ": " + e.getMessage(), 4); - } - } - } - return currentlyEnabled; - } + if (currentlyEnabled) + Miscellaneous.logEvent("i", "isWifiApEnabled", "true", 5); + else + Miscellaneous.logEvent("i", "isWifiApEnabled", "false", 5); + } + catch (Exception e) + { + Miscellaneous.logEvent("i", "isWifiApEnabled", context.getResources().getString(R.string.errorDeterminingWifiApState) + ": " + e.getMessage(), 4); + } + } + } + return currentlyEnabled; + } - public static Boolean setWifiTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "WifiTethering", "Changing WifiTethering to " + String.valueOf(desiredState), 4); + public static Boolean setWifiTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "WifiTethering", "Changing WifiTethering to " + String.valueOf(desiredState), 4); - boolean state = Actions.isWifiApEnabled(context); + boolean state = Actions.isWifiApEnabled(context); - if (toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.toggling), 2); - desiredState = !state; - } + if (toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.toggling), 2); + desiredState = !state; + } - if (((state && !desiredState) || (!state && desiredState))) - { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - { - WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - Method[] methods = wifiManager.getClass().getDeclaredMethods(); - for (Method method : methods) - { - Miscellaneous.logEvent("i", "WifiAp", "Trying to find appropriate method... " + method.getName(), 5); - if (method.getName().equals("setWifiApEnabled")) - { - try - { - String desiredString = ""; - if (desiredState) - desiredString = "activate"; - else - desiredString = "deactivate"; + if (((state && !desiredState) || (!state && desiredState))) + { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) + { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + Method[] methods = wifiManager.getClass().getDeclaredMethods(); + for (Method method : methods) + { + Miscellaneous.logEvent("i", "WifiAp", "Trying to find appropriate method... " + method.getName(), 5); + if (method.getName().equals("setWifiApEnabled")) + { + try + { + String desiredString = ""; + if (desiredState) + desiredString = "activate"; + else + desiredString = "deactivate"; - if (!toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "WifiAp", "Trying to " + desiredString + " wifi ap...", 2); - if (!method.isAccessible()) - method.setAccessible(true); - method.invoke(wifiManager, null, desiredState); - } - else - { - Miscellaneous.logEvent("i", "WifiAp", "Trying to " + context.getResources().getString(R.string.toggle) + " wifi ap...", 2); - if (!method.isAccessible()) - method.setAccessible(true); - method.invoke(wifiManager, null, !state); - } + if (!toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "WifiAp", "Trying to " + desiredString + " wifi ap...", 2); + if (!method.isAccessible()) + method.setAccessible(true); + method.invoke(wifiManager, null, desiredState); + } + else + { + Miscellaneous.logEvent("i", "WifiAp", "Trying to " + context.getResources().getString(R.string.toggle) + " wifi ap...", 2); + if (!method.isAccessible()) + method.setAccessible(true); + method.invoke(wifiManager, null, !state); + } - Miscellaneous.logEvent("i", "WifiAp", "Wifi ap " + desiredString + "d.", 2); - } - catch (Exception e) - { - Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.errorActivatingWifiAp) + ". " + e.getMessage(), 2); - } - } - } - } - else - { - MyOnStartTetheringCallback cb = new MyOnStartTetheringCallback() - { - @Override - public void onTetheringStarted() - { - Log.i("Tether", "Läuft"); - } + Miscellaneous.logEvent("i", "WifiAp", "Wifi ap " + desiredString + "d.", 2); + } + catch (Exception e) + { + Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.errorActivatingWifiAp) + ". " + e.getMessage(), 2); + } + } + } + } + else + { + MyOnStartTetheringCallback cb = new MyOnStartTetheringCallback() + { + @Override + public void onTetheringStarted() + { + Log.i("Tether", "Läuft"); + } - @Override - public void onTetheringFailed() - { - Log.i("Tether", "Doof"); - } - }; + @Override + public void onTetheringFailed() + { + Log.i("Tether", "Doof"); + } + }; - MyOreoWifiManager mowm = new MyOreoWifiManager(context); - if (desiredState) - mowm.startTethering(cb); - else - mowm.stopTethering(); - } - } - return true; - } + MyOreoWifiManager mowm = new MyOreoWifiManager(context); + if (desiredState) + mowm.startTethering(cb); + else + mowm.stopTethering(); + } + } + return true; + } - public static class BluetoothTetheringClass - { - static Object instance = null; - static Method setTetheringOn = null; - static Method isTetheringOn = null; - static Object mutex = new Object(); + public static class BluetoothTetheringClass + { + static Object instance = null; + static Method setTetheringOn = null; + static Method isTetheringOn = null; + static Object mutex = new Object(); - public static Boolean setBluetoothTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "Bluetooth Tethering", "Changing Bluetooth Tethering to " + String.valueOf(desiredState), 4); + public static Boolean setBluetoothTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "Bluetooth Tethering", "Changing Bluetooth Tethering to " + String.valueOf(desiredState), 4); // boolean state = isTetheringOn(context); @@ -525,351 +525,351 @@ public class Actions // if (((state && !desiredState) || (!state && desiredState))) // { - BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - Class classBluetoothPan = null; - Constructor BTPanCtor = null; - Object BTSrvInstance = null; - Method mBTPanConnect = null; + BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + Class classBluetoothPan = null; + Constructor BTPanCtor = null; + Object BTSrvInstance = null; + Method mBTPanConnect = null; - String sClassName = "android.bluetooth.BluetoothPan"; - try - { - classBluetoothPan = Class.forName(sClassName); - Constructor ctor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class); + String sClassName = "android.bluetooth.BluetoothPan"; + try + { + classBluetoothPan = Class.forName(sClassName); + Constructor ctor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class); - ctor.setAccessible(true); - // Set Tethering ON + ctor.setAccessible(true); + // Set Tethering ON - Class[] paramSet = new Class[1]; - paramSet[0] = boolean.class; + Class[] paramSet = new Class[1]; + paramSet[0] = boolean.class; - synchronized (mutex) - { - setTetheringOn = classBluetoothPan.getDeclaredMethod("setBluetoothTethering", paramSet); - isTetheringOn = classBluetoothPan.getDeclaredMethod("isTetheringOn", null); - instance = ctor.newInstance(context, new BTPanServiceListener(context)); - } + synchronized (mutex) + { + setTetheringOn = classBluetoothPan.getDeclaredMethod("setBluetoothTethering", paramSet); + isTetheringOn = classBluetoothPan.getDeclaredMethod("isTetheringOn", null); + instance = ctor.newInstance(context, new BTPanServiceListener(context)); + } - classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan"); - mBTPanConnect = classBluetoothPan.getDeclaredMethod("connect", BluetoothDevice.class); - BTPanCtor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class); - BTPanCtor.setAccessible(true); - BTSrvInstance = BTPanCtor.newInstance(context, new BTPanServiceListener(context)); + classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan"); + mBTPanConnect = classBluetoothPan.getDeclaredMethod("connect", BluetoothDevice.class); + BTPanCtor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class); + BTPanCtor.setAccessible(true); + BTSrvInstance = BTPanCtor.newInstance(context, new BTPanServiceListener(context)); - Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); - // If there are paired devices - if (pairedDevices.size() > 0) - { - // Loop through paired devices - for (BluetoothDevice device : pairedDevices) - { - try - { - mBTPanConnect.invoke(BTSrvInstance, device); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } - } - } - return true; - } - catch (NoSuchMethodException e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } - catch (ClassNotFoundException e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } - catch(InvocationTargetException e) - { + // If there are paired devices + if (pairedDevices.size() > 0) + { + // Loop through paired devices + for (BluetoothDevice device : pairedDevices) + { + try + { + mBTPanConnect.invoke(BTSrvInstance, device); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } + } + } + return true; + } + catch (NoSuchMethodException e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } + catch (ClassNotFoundException e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } + catch (InvocationTargetException e) + { /* Exact error message: "Bluetooth binder is null" This means this device doesn't have bluetooth. */ - Miscellaneous.logEvent("e", "Bluetooth Tethering", "Device probably doesn't have bluetooth. " + Log.getStackTraceString(e), 1); - Toast.makeText(context, context.getResources().getString(R.string.deviceDoesNotHaveBluetooth), Toast.LENGTH_SHORT).show(); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } + Miscellaneous.logEvent("e", "Bluetooth Tethering", "Device probably doesn't have bluetooth. " + Log.getStackTraceString(e), 1); + Toast.makeText(context, context.getResources().getString(R.string.deviceDoesNotHaveBluetooth), Toast.LENGTH_SHORT).show(); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } - return false; - } + return false; + } - public static class BTPanServiceListener implements BluetoothProfile.ServiceListener - { - private final Context context; + public static class BTPanServiceListener implements BluetoothProfile.ServiceListener + { + private final Context context; - public BTPanServiceListener(final Context context) - { - this.context = context; - } + public BTPanServiceListener(final Context context) + { + this.context = context; + } - @Override - public void onServiceConnected(final int profile, final BluetoothProfile proxy) - { - //Some code must be here or the compiler will optimize away this callback. + @Override + public void onServiceConnected(final int profile, final BluetoothProfile proxy) + { + //Some code must be here or the compiler will optimize away this callback. - try - { - synchronized (mutex) - { - setTetheringOn.invoke(instance, true); - if ((Boolean) isTetheringOn.invoke(instance, null)) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", "BT Tethering is on", 1); - } - else - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", "BT Tethering is off", 1); - } - } - } - catch (InvocationTargetException e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } - catch (IllegalAccessException e) - { - Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); - } - } + try + { + synchronized (mutex) + { + setTetheringOn.invoke(instance, true); + if ((Boolean) isTetheringOn.invoke(instance, null)) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", "BT Tethering is on", 1); + } + else + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", "BT Tethering is off", 1); + } + } + } + catch (InvocationTargetException e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } + catch (IllegalAccessException e) + { + Miscellaneous.logEvent("e", "Bluetooth Tethering", Log.getStackTraceString(e), 1); + } + } - @Override - public void onServiceDisconnected(final int profile) - { - } - } - } + @Override + public void onServiceDisconnected(final int profile) + { + } + } + } - public static boolean setUsbTethering(Context context2, Boolean desiredState, boolean toggleActionIfPossible) - { - //TODO:toggle not really implemented, yet + public static boolean setUsbTethering(Context context2, Boolean desiredState, boolean toggleActionIfPossible) + { + //TODO:toggle not really implemented, yet - Miscellaneous.logEvent("i", "UsbTethering", "Changing UsbTethering to " + String.valueOf(desiredState), 4); + Miscellaneous.logEvent("i", "UsbTethering", "Changing UsbTethering to " + String.valueOf(desiredState), 4); - boolean state = false; //Actions.isWifiApEnabled(context); - Object connectivityServiceObject = null; - ConnectivityManager connMgr = null; + boolean state = false; //Actions.isWifiApEnabled(context); + Object connectivityServiceObject = null; + ConnectivityManager connMgr = null; - try - { - connectivityServiceObject = context.getSystemService(Context.CONNECTIVITY_SERVICE); - connMgr = (ConnectivityManager) connectivityServiceObject; - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "UsbTethering", context2.getResources().getString(R.string.logErrorGettingConnectionManagerService), 2); - return false; - } + try + { + connectivityServiceObject = context.getSystemService(Context.CONNECTIVITY_SERVICE); + connMgr = (ConnectivityManager) connectivityServiceObject; + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "UsbTethering", context2.getResources().getString(R.string.logErrorGettingConnectionManagerService), 2); + return false; + } - try - { - if ((state && !desiredState) || (!state && desiredState)) - { - try - { - Method method = connectivityServiceObject.getClass().getDeclaredMethod("getTetheredIfaces"); - if (!method.isAccessible()) - method.setAccessible(true); - String[] tetheredInterfaces = (String[]) method.invoke(connectivityServiceObject); - if (tetheredInterfaces.length > 0) - state = true; - } - catch (NoSuchMethodException e) - { - // System doesn't have that method, try another way + try + { + if ((state && !desiredState) || (!state && desiredState)) + { + try + { + Method method = connectivityServiceObject.getClass().getDeclaredMethod("getTetheredIfaces"); + if (!method.isAccessible()) + method.setAccessible(true); + String[] tetheredInterfaces = (String[]) method.invoke(connectivityServiceObject); + if (tetheredInterfaces.length > 0) + state = true; + } + catch (NoSuchMethodException e) + { + // System doesn't have that method, try another way - String ipAddr = getIPAddressUsb(true); - if (ipAddr.length() == 0) - state = false; // tethering not enabled - else - state = true; // tethering enabled - } - } - } - catch (Exception e) - { - Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.logErrorDeterminingCurrentUsbTetheringState), 3); - } + String ipAddr = getIPAddressUsb(true); + if (ipAddr.length() == 0) + state = false; // tethering not enabled + else + state = true; // tethering enabled + } + } + } + catch (Exception e) + { + Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.logErrorDeterminingCurrentUsbTetheringState), 3); + } - if (toggleActionIfPossible) - { - Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.toggling), 3); - desiredState = !state; - } + if (toggleActionIfPossible) + { + Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.toggling), 3); + desiredState = !state; + } - if ((state && !desiredState) || (!state && desiredState)) - { - String desiredString = ""; - if (desiredState) - desiredString = "activate"; - else - desiredString = "deactivate"; + if ((state && !desiredState) || (!state && desiredState)) + { + String desiredString = ""; + if (desiredState) + desiredString = "activate"; + else + desiredString = "deactivate"; - try - { - Method method = null; + try + { + Method method = null; - for (Method m : connectivityServiceObject.getClass().getDeclaredMethods()) - { - if (desiredState && m.getName().equals("tether")) - { - method = m; - break; - } + for (Method m : connectivityServiceObject.getClass().getDeclaredMethods()) + { + if (desiredState && m.getName().equals("tether")) + { + method = m; + break; + } - if (!desiredState && m.getName().equals("untether")) - { - method = m; - break; - } - } + if (!desiredState && m.getName().equals("untether")) + { + method = m; + break; + } + } - if (method == null) - throw new NoSuchMethodException(); + if (method == null) + throw new NoSuchMethodException(); - /* - * For some reason this doesn't work, throws NoSuchMethodExpection even if the method is present. - */ + /* + * For some reason this doesn't work, throws NoSuchMethodExpection even if the method is present. + */ // if(desiredState) // method = connectivityServiceObject.getClass().getDeclaredMethod("tether"); // else // method = connectivityServiceObject.getClass().getDeclaredMethod("untether"); - // DETECT INTERFACE NAME - Miscellaneous.logEvent("i", "UsbTethering", context2.getResources().getString(R.string.logDetectingTetherableUsbInterface), 4); - String[] available = null; - Method[] wmMethods = connMgr.getClass().getDeclaredMethods(); - for (Method getMethod : wmMethods) - { - if (getMethod.getName().equals("getTetherableUsbRegexs")) - { - try - { - if (!method.isAccessible()) - method.setAccessible(true); - available = (String[]) getMethod.invoke(connMgr); + // DETECT INTERFACE NAME + Miscellaneous.logEvent("i", "UsbTethering", context2.getResources().getString(R.string.logDetectingTetherableUsbInterface), 4); + String[] available = null; + Method[] wmMethods = connMgr.getClass().getDeclaredMethods(); + for (Method getMethod : wmMethods) + { + if (getMethod.getName().equals("getTetherableUsbRegexs")) + { + try + { + if (!method.isAccessible()) + method.setAccessible(true); + available = (String[]) getMethod.invoke(connMgr); // break; - } - catch (Exception e) - { - e.printStackTrace(); - } - } - } - // DETECT INTERFACE NAME + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + // DETECT INTERFACE NAME - if (available.length > 0) - { - for (String interfaceName : available) - { - Miscellaneous.logEvent("i", "UsbTethering", "Detected " + String.valueOf(available.length) + " tetherable usb interfaces.", 5); - Miscellaneous.logEvent("i", "UsbTethering", "Trying to " + desiredString + " UsbTethering on interface " + interfaceName + "...", 5); - if (!method.isAccessible()) - method.setAccessible(true); - Integer returnCode = (Integer) method.invoke(connectivityServiceObject, interfaceName); - if (returnCode == 0) - { - Miscellaneous.logEvent("i", "UsbTethering", "UsbTethering " + desiredString + "d.", 5); - return true; - } - else - { - Miscellaneous.logEvent("w", "UsbTethering", "Failed to " + desiredString + "Usb Tethering. ReturnCode of method " + method.getName() + ": " + String.valueOf(returnCode), 5); - } - } - } - } - catch (NoSuchMethodException e) - { - Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. This kind of error may indicate we are above Android 2.3: " + Log.getStackTraceString(e), 3); - } - catch (Exception e) - { - Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. " + Log.getStackTraceString(e), 3); - } - } - return false; - } + if (available.length > 0) + { + for (String interfaceName : available) + { + Miscellaneous.logEvent("i", "UsbTethering", "Detected " + String.valueOf(available.length) + " tetherable usb interfaces.", 5); + Miscellaneous.logEvent("i", "UsbTethering", "Trying to " + desiredString + " UsbTethering on interface " + interfaceName + "...", 5); + if (!method.isAccessible()) + method.setAccessible(true); + Integer returnCode = (Integer) method.invoke(connectivityServiceObject, interfaceName); + if (returnCode == 0) + { + Miscellaneous.logEvent("i", "UsbTethering", "UsbTethering " + desiredString + "d.", 5); + return true; + } + else + { + Miscellaneous.logEvent("w", "UsbTethering", "Failed to " + desiredString + "Usb Tethering. ReturnCode of method " + method.getName() + ": " + String.valueOf(returnCode), 5); + } + } + } + } + catch (NoSuchMethodException e) + { + Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. This kind of error may indicate we are above Android 2.3: " + Log.getStackTraceString(e), 3); + } + catch (Exception e) + { + Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. " + Log.getStackTraceString(e), 3); + } + } + return false; + } - public static Boolean setBluetooth(Context context, Boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "Bluetooth", "Changing bluetooth to " + String.valueOf(desiredState), 4); + public static Boolean setBluetooth(Context context, Boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "Bluetooth", "Changing bluetooth to " + String.valueOf(desiredState), 4); - try - { - BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + try + { + BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - // toggle - if (toggleActionIfPossible) - { - Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.toggling), 2); - desiredState = !myBluetoothAdapter.isEnabled(); - } + // toggle + if (toggleActionIfPossible) + { + Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.toggling), 2); + desiredState = !myBluetoothAdapter.isEnabled(); + } - // activate - if (!myBluetoothAdapter.isEnabled() && desiredState) - { - Toast.makeText(context, context.getResources().getString(R.string.activating) + " Bluetooth.", Toast.LENGTH_LONG).show(); - myBluetoothAdapter.enable(); - return true; - } + // activate + if (!myBluetoothAdapter.isEnabled() && desiredState) + { + Toast.makeText(context, context.getResources().getString(R.string.activating) + " Bluetooth.", Toast.LENGTH_LONG).show(); + myBluetoothAdapter.enable(); + return true; + } - // deactivate - if (myBluetoothAdapter.isEnabled() && !desiredState) - { - Toast.makeText(context, context.getResources().getString(R.string.deactivating) + " Bluetooth.", Toast.LENGTH_LONG).show(); - myBluetoothAdapter.disable(); - return true; - } - } - catch (NullPointerException e) - { - Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.failedToTriggerBluetooth), 2); - Toast.makeText(context, context.getResources().getString(R.string.bluetoothFailed), Toast.LENGTH_LONG).show(); - } + // deactivate + if (myBluetoothAdapter.isEnabled() && !desiredState) + { + Toast.makeText(context, context.getResources().getString(R.string.deactivating) + " Bluetooth.", Toast.LENGTH_LONG).show(); + myBluetoothAdapter.disable(); + return true; + } + } + catch (NullPointerException e) + { + Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.failedToTriggerBluetooth), 2); + Toast.makeText(context, context.getResources().getString(R.string.bluetoothFailed), Toast.LENGTH_LONG).show(); + } - return false; - } + return false; + } - public static void setDoNotDisturb(Context context, int desiredDndMode) - { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - { + public static void setDoNotDisturb(Context context, int desiredDndMode) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + { /* if (!notificationManager.isNotificationPolicyAccessGranted()) --> done externally */ - Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing DND to " + String.valueOf(desiredDndMode), 4); - NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationManager.setInterruptionFilter(desiredDndMode); - } - else - Miscellaneous.logEvent("w", context.getResources().getString(R.string.soundSettings), "Cannot change DND to " + String.valueOf(desiredDndMode) + ". This Android version is too and doesn\'t have that feature, yet.", 4); - } + Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing DND to " + String.valueOf(desiredDndMode), 4); + NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + mNotificationManager.setInterruptionFilter(desiredDndMode); + } + else + Miscellaneous.logEvent("w", context.getResources().getString(R.string.soundSettings), "Cannot change DND to " + String.valueOf(desiredDndMode) + ". This Android version is too and doesn\'t have that feature, yet.", 4); + } - @RequiresApi(api = Build.VERSION_CODES.M) - public static boolean isDoNotDisturbActive(Context context) - { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - int result = notificationManager.getCurrentInterruptionFilter(); - return (notificationManager.getCurrentInterruptionFilter() != NotificationManager.INTERRUPTION_FILTER_ALL); - } + @RequiresApi(api = Build.VERSION_CODES.M) + public static boolean isDoNotDisturbActive(Context context) + { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + int result = notificationManager.getCurrentInterruptionFilter(); + return (notificationManager.getCurrentInterruptionFilter() != NotificationManager.INTERRUPTION_FILTER_ALL); + } - public static void setSound(Context context, int desiredSoundSetting) - { - Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing sound to " + String.valueOf(desiredSoundSetting), 4); + public static void setSound(Context context, int desiredSoundSetting) + { + Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing sound to " + String.valueOf(desiredSoundSetting), 4); - AudioManager myAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + AudioManager myAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && desiredSoundSetting == AudioManager.RINGER_MODE_SILENT) // { @@ -878,131 +878,131 @@ public class Actions // am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF); // } // else - myAudioManager.setRingerMode(desiredSoundSetting); - } + myAudioManager.setRingerMode(desiredSoundSetting); + } - private static String getIPAddressUsb(final boolean useIPv4) - { - try - { - final List interfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); - for (final NetworkInterface intf : interfaces) - { - if (intf.getDisplayName().startsWith("usb")) // ro "rndis0" - { - final List addrs = Collections.list(intf.getInetAddresses()); - for (final InetAddress addr : addrs) - { - final String sAddr = addr.getHostAddress().toUpperCase(); - final boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr); - if (useIPv4) - { - if (isIPv4) - { - return sAddr; - } - } - else - { - if (!isIPv4) - { - final int delim = sAddr.indexOf('%'); - return delim < 0 ? sAddr : sAddr.substring(0, delim); - } - } - } - } - } - } - catch (final Exception ex) - { - // for now eat exceptions - } - return ""; - } + private static String getIPAddressUsb(final boolean useIPv4) + { + try + { + final List interfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); + for (final NetworkInterface intf : interfaces) + { + if (intf.getDisplayName().startsWith("usb")) // ro "rndis0" + { + final List addrs = Collections.list(intf.getInetAddresses()); + for (final InetAddress addr : addrs) + { + final String sAddr = addr.getHostAddress().toUpperCase(); + final boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr); + if (useIPv4) + { + if (isIPv4) + { + return sAddr; + } + } + else + { + if (!isIPv4) + { + final int delim = sAddr.indexOf('%'); + return delim < 0 ? sAddr : sAddr.substring(0, delim); + } + } + } + } + } + } + catch (final Exception ex) + { + // for now eat exceptions + } + return ""; + } - public static void playSound(boolean alwaysPlay, String soundFileLocation) - { - if (alwaysPlay || ((AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE)).getRingerMode() == AudioManager.RINGER_MODE_NORMAL) - { - MediaPlayer mp = new MediaPlayer(); - try - { - File file = new File(soundFileLocation); - if (file.exists()) - { - Uri fileUri = Uri.parse(soundFileLocation); - mp.setLooping(false); - mp.setDataSource(Miscellaneous.getAnyContext(), fileUri); - mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() - { - @Override - public void onCompletion(MediaPlayer mp) - { - mp.release(); - } - }); - mp.prepare(); - mp.start(); - } - else - { - Miscellaneous.logEvent("w", "Play sound file", "Sound file " + soundFileLocation + " does not exist. Can't play it.", 2); - Toast.makeText(context, String.format(context.getResources().getString(R.string.cantFindSoundFile), soundFileLocation), Toast.LENGTH_SHORT).show(); - } - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "Play sound file", "Error playing sound: " + Log.getStackTraceString(e), 2); - } - } - else - Miscellaneous.logEvent("i", "Play sound file", "Not playing sound file because phone is on some kind of mute state.", 2); - } + public static void playSound(boolean alwaysPlay, String soundFileLocation) + { + if (alwaysPlay || ((AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE)).getRingerMode() == AudioManager.RINGER_MODE_NORMAL) + { + MediaPlayer mp = new MediaPlayer(); + try + { + File file = new File(soundFileLocation); + if (file.exists()) + { + Uri fileUri = Uri.parse(soundFileLocation); + mp.setLooping(false); + mp.setDataSource(Miscellaneous.getAnyContext(), fileUri); + mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() + { + @Override + public void onCompletion(MediaPlayer mp) + { + mp.release(); + } + }); + mp.prepare(); + mp.start(); + } + else + { + Miscellaneous.logEvent("w", "Play sound file", "Sound file " + soundFileLocation + " does not exist. Can't play it.", 2); + Toast.makeText(context, String.format(context.getResources().getString(R.string.cantFindSoundFile), soundFileLocation), Toast.LENGTH_SHORT).show(); + } + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Play sound file", "Error playing sound: " + Log.getStackTraceString(e), 2); + } + } + else + Miscellaneous.logEvent("i", "Play sound file", "Not playing sound file because phone is on some kind of mute state.", 2); + } public static void vibrate(boolean parameter1, String parameter2) { - String vibrateDurations[] = parameter2.split(Action.vibrateSeparator); + String vibrateDurations[] = parameter2.split(Action.vibrateSeparator); - int counter = 1; - for(String vibrate : vibrateDurations) - { - if(counter % 2 != 0) - { - Vibrator vibrator = (Vibrator) Miscellaneous.getAnyContext().getSystemService(Context.VIBRATOR_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - vibrator.vibrate(VibrationEffect.createOneShot(Long.parseLong(vibrate), VibrationEffect.DEFAULT_AMPLITUDE)); - else - vibrator.vibrate(Long.parseLong(vibrate)); - } - else - { - try - { - Thread.sleep(Long.parseLong(vibrate)); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "VibrateSleep", Log.getStackTraceString(e), 5); - } - } + int counter = 1; + for (String vibrate : vibrateDurations) + { + if (counter % 2 != 0) + { + Vibrator vibrator = (Vibrator) Miscellaneous.getAnyContext().getSystemService(Context.VIBRATOR_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + vibrator.vibrate(VibrationEffect.createOneShot(Long.parseLong(vibrate), VibrationEffect.DEFAULT_AMPLITUDE)); + else + vibrator.vibrate(Long.parseLong(vibrate)); + } + else + { + try + { + Thread.sleep(Long.parseLong(vibrate)); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "VibrateSleep", Log.getStackTraceString(e), 5); + } + } - counter++; - } + counter++; + } } - public void useDownloadedWebpage(String result) - { + public void useDownloadedWebpage(String result) + { // Toast.makeText(context, "Result: " + result, Toast.LENGTH_LONG).show(); - Actions.setVariable("last_triggerurl_result" + Action.actionParameter2Split + result); - } + Actions.setVariable("last_triggerurl_result" + Action.actionParameter2Split + result); + } - public static HttpClient getInsecureSslClient(HttpClient client) - { - try - { - SSLContext ctx = SSLContext.getInstance("TLS"); - SSLSocketFactory ssf = null; + public static HttpClient getInsecureSslClient(HttpClient client) + { + try + { + SSLContext ctx = SSLContext.getInstance("TLS"); + SSLSocketFactory ssf = null; // MySSLSocketFactoryInsecure ssfI = null; // if(!Settings.httpAcceptAllCertificates) @@ -1025,123 +1025,124 @@ public class Actions // } // else // { - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustStore.load(null, null); - ssf = new MySSLSocketFactoryInsecure(trustStore); - ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - ctx.init(null, null, null); + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + ssf = new MySSLSocketFactoryInsecure(trustStore); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ctx.init(null, null, null); // } - ClientConnectionManager ccm = client.getConnectionManager(); - SchemeRegistry sr = ccm.getSchemeRegistry(); + ClientConnectionManager ccm = client.getConnectionManager(); + SchemeRegistry sr = ccm.getSchemeRegistry(); // if(!Settings.httpAcceptAllCertificates) - sr.register(new Scheme("https", ssf, 443)); + sr.register(new Scheme("https", ssf, 443)); // else // sr.register(new Scheme("https", ssfI, 443)); - return new DefaultHttpClient(ccm, client.getParams()); - } - catch (Exception ex) - { - ex.printStackTrace(); - return null; - } - } + return new DefaultHttpClient(ccm, client.getParams()); + } + catch (Exception ex) + { + ex.printStackTrace(); + return null; + } + } - public static void startOtherActivity(boolean startByAction, String param) - { - Miscellaneous.logEvent("i", "StartOtherActivity", "Starting other Activity...", 4); + public static void startOtherActivity(boolean startByAction, String param) + { + Miscellaneous.logEvent("i", "StartOtherActivity", "Starting other Activity...", 4); - String[] params; + String[] params; - if(param.contains(Action.actionParameter2Split)) - params = param.split(Action.actionParameter2Split, -1); - else - params = param.split(";", -1); + if (param.contains(Action.actionParameter2Split)) + params = param.split(Action.actionParameter2Split, -1); + else + params = param.split(";", -1); - try - { - Intent externalApplicationIntent; + try + { + Intent externalApplicationIntent; - String packageName, className, activityOrAction, startupType; + String packageName, className, activityOrAction, startupType; - packageName = params[0]; - className = params[1]; - activityOrAction = params[2]; - startupType = params[3]; + packageName = params[0]; + className = params[1]; + activityOrAction = params[2]; + startupType = params[3]; - if (!startByAction) - { - // start by activity - Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by activity: " + packageName + " " + className, 3); + if (!startByAction) + { + // start by activity + Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by activity: " + packageName + " " + className, 3); - externalApplicationIntent = new Intent(Intent.ACTION_MAIN); - externalApplicationIntent.addCategory(Intent.CATEGORY_LAUNCHER); + externalApplicationIntent = new Intent(Intent.ACTION_MAIN); + externalApplicationIntent.addCategory(Intent.CATEGORY_LAUNCHER); - if(packageName.equals("dummyPkg") || packageName.length() == 0) - externalApplicationIntent.setAction(className); + if (packageName.equals("dummyPkg") || packageName.length() == 0) + externalApplicationIntent.setAction(className); - externalApplicationIntent.setPackage(packageName); - externalApplicationIntent.setClassName(packageName, activityOrAction); + externalApplicationIntent.setPackage(packageName); + externalApplicationIntent.setClassName(packageName, activityOrAction); - if (!Miscellaneous.doesActivityExist(externalApplicationIntent, Miscellaneous.getAnyContext())) - Miscellaneous.logEvent("w", "StartOtherApp", "Activity not found: " + className, 2); - } - else - { - // start by action - Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by action: " + param, 3); + if (!Miscellaneous.doesActivityExist(externalApplicationIntent, Miscellaneous.getAnyContext())) + Miscellaneous.logEvent("w", "StartOtherApp", "Activity not found: " + className, 2); + } + else + { + // start by action + Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by action: " + param, 3); - externalApplicationIntent = new Intent(); + externalApplicationIntent = new Intent(); - if (!packageName.equals(dummyPackageString)) - { - externalApplicationIntent.setPackage(packageName); - if(!StringUtils.isEmpty(className)) - externalApplicationIntent.setClassName(packageName, className); - } + if (!packageName.equals(dummyPackageString)) + { + externalApplicationIntent.setPackage(packageName); + if (!StringUtils.isEmpty(className)) + externalApplicationIntent.setClassName(packageName, className); + } - externalApplicationIntent.setAction(activityOrAction); + externalApplicationIntent.setAction(activityOrAction); - if (startupType.equals(ActivityManageActionStartActivity.startByServiceString) || startupType.equals(ActivityManageActionStartActivity.startByForegroundServiceString)) - { - externalApplicationIntent.setComponent(new ComponentName(packageName, className)); - } - } + if (startupType.equals(ActivityManageActionStartActivity.startByServiceString) || startupType.equals(ActivityManageActionStartActivity.startByForegroundServiceString)) + { + externalApplicationIntent.setComponent(new ComponentName(packageName, className)); + } + } - externalApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + externalApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); +// externalApplicationIntent.setType(android.intent.extra.) - // Pack intents - if(params.length >= 5) - { - if(Miscellaneous.isNumeric(startupType)) - externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 4); - else - externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 3); - } + // Pack intents + if (params.length >= 5) + { + if (Miscellaneous.isNumeric(startupType)) + externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 4); + else + externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 3); + } - if (startupType.equals(ActivityManageActionStartActivity.startByActivityString)) - automationServerRef.startActivity(externalApplicationIntent); - else if (startupType.equals(ActivityManageActionStartActivity.startByServiceString)) - automationServerRef.startService(externalApplicationIntent); - else if (startupType.equals(ActivityManageActionStartActivity.startByForegroundServiceString) && Build.VERSION.SDK_INT >= 26) - automationServerRef.startForegroundService(externalApplicationIntent); - else - automationServerRef.sendBroadcast(externalApplicationIntent); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "StartOtherApp", automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2); - Toast.makeText(automationServerRef, automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + e.getMessage(), Toast.LENGTH_LONG).show(); - } - } + if (startupType.equals(ActivityManageActionStartActivity.startByActivityString)) + automationServerRef.startActivity(externalApplicationIntent); + else if (startupType.equals(ActivityManageActionStartActivity.startByServiceString)) + automationServerRef.startService(externalApplicationIntent); + else if (startupType.equals(ActivityManageActionStartActivity.startByForegroundServiceString) && Build.VERSION.SDK_INT >= 26) + automationServerRef.startForegroundService(externalApplicationIntent); + else + automationServerRef.sendBroadcast(externalApplicationIntent); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "StartOtherApp", automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2); + Toast.makeText(automationServerRef, automationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + e.getMessage(), Toast.LENGTH_LONG).show(); + } + } - 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); + 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()) @@ -1153,224 +1154,224 @@ public class Actions } }*/ - 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")) - { - try - { - 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(Miscellaneous.replaceVariablesInText(singleParam[2], context))); + 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")) + { + try + { + 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(Miscellaneous.replaceVariablesInText(singleParam[2], context))); - } - 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(Miscellaneous.replaceVariablesInText(singleParam[2], context))); - } - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - 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); - try - { - intent.putExtra(singleParam[1], Miscellaneous.replaceVariablesInText(singleParam[2], context)); - } - catch (Exception e) - { - 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); - } + } + 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(Miscellaneous.replaceVariablesInText(singleParam[2], context))); + } + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + 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); + try + { + intent.putExtra(singleParam[1], Miscellaneous.replaceVariablesInText(singleParam[2], context)); + } + catch (Exception e) + { + 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; - } + return intent; + } - public static void waitBeforeNextAction(Long waitTime) - { - Miscellaneous.logEvent("i", "waitBeforeNextAction", "waitBeforeNextAction for " + String.valueOf(waitTime) + " milliseconds.", 4); + public static void waitBeforeNextAction(Long waitTime) + { + Miscellaneous.logEvent("i", "waitBeforeNextAction", "waitBeforeNextAction for " + String.valueOf(waitTime) + " milliseconds.", 4); - try - { - Thread.sleep(waitTime); - } - catch (InterruptedException e) - { - Miscellaneous.logEvent("e", "waitBeforeNextAction", Log.getStackTraceString(e), 2); - } - } + try + { + Thread.sleep(waitTime); + } + catch (InterruptedException e) + { + Miscellaneous.logEvent("e", "waitBeforeNextAction", Log.getStackTraceString(e), 2); + } + } - public static void wakeupDevice(Long awakeTime) - { - String duration = "default"; - if (awakeTime > 0) - duration = String.valueOf(awakeTime) + " milliseconds"; + public static void wakeupDevice(Long awakeTime) + { + String duration = "default"; + if (awakeTime > 0) + duration = String.valueOf(awakeTime) + " milliseconds"; - Miscellaneous.logEvent("i", "wakeupDevice", "wakeupDevice for " + String.valueOf(duration) + ".", 4); + Miscellaneous.logEvent("i", "wakeupDevice", "wakeupDevice for " + String.valueOf(duration) + ".", 4); - if (awakeTime > 0) - { - /* - * This action needs to be performed in a separate thread. If it ran in the same one - * the screen would turn on, the specified amount of time would pass and the screen - * would turn off again before any other action in the rule would be ran. - */ - Thread t = new Thread(new WakeUpDeviceClass(awakeTime)); - t.start(); - } - } + if (awakeTime > 0) + { + /* + * This action needs to be performed in a separate thread. If it ran in the same one + * the screen would turn on, the specified amount of time would pass and the screen + * would turn off again before any other action in the rule would be ran. + */ + Thread t = new Thread(new WakeUpDeviceClass(awakeTime)); + t.start(); + } + } - public static void sendTextMessage(Context context, String[] parametersArray) - { - String phoneNumber, message, messageType = ActivityManageActionSendTextMessage.messageTypeSms, filePath = null; + public static void sendTextMessage(Context context, String[] parametersArray) + { + String phoneNumber, message, messageType = ActivityManageActionSendTextMessage.messageTypeSms, filePath = null; - phoneNumber = parametersArray[0]; - message = parametersArray[1]; + phoneNumber = parametersArray[0]; + message = parametersArray[1]; - if(parametersArray.length > 2) - { - messageType = parametersArray[2]; + if (parametersArray.length > 2) + { + messageType = parametersArray[2]; - if(parametersArray.length > 3) - filePath = parametersArray[3]; - } + if (parametersArray.length > 3) + filePath = parametersArray[3]; + } - try - { - String textToSend = Miscellaneous.replaceVariablesInText(message, context); - if(messageType.equals("sms")) - sendSmsMessage(phoneNumber, textToSend); - else - sendMmsMessage(phoneNumber, textToSend, filePath); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3); - } - } + try + { + String textToSend = Miscellaneous.replaceVariablesInText(message, context); + if (messageType.equals("sms")) + sendSmsMessage(phoneNumber, textToSend); + else + sendMmsMessage(phoneNumber, textToSend, filePath); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3); + } + } - private static void sendSmsMessage(String phoneNumber, String textToSend) - { - try - { - PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, Actions.class), 0); - SmsManager sms = SmsManager.getDefault(); - sms.sendTextMessage(phoneNumber, null, textToSend, pi, null); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3); - } - } + private static void sendSmsMessage(String phoneNumber, String textToSend) + { + try + { + PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, Actions.class), 0); + SmsManager sms = SmsManager.getDefault(); + sms.sendTextMessage(phoneNumber, null, textToSend, pi, null); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3); + } + } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private static void sendMmsMessage(String phoneNumber, String textToSend, String fileToBeAttached) - { - try - { - Miscellaneous.logEvent("i", "sendMmsMessage()", "Sending MMS message...", 2); + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static void sendMmsMessage(String phoneNumber, String textToSend, String fileToBeAttached) + { + try + { + Miscellaneous.logEvent("i", "sendMmsMessage()", "Sending MMS message...", 2); // Uri contentUri = Uri.fromFile(new File(fileToBeAttached)); - String str2 = "send." + String.valueOf(Math.abs(new Random().nextLong())) + ".dat"; - Uri contentUri = new Uri.Builder().authority(context.getPackageName() + ".MmsFileProvider").path(str2).scheme("content").build(); + String str2 = "send." + String.valueOf(Math.abs(new Random().nextLong())) + ".dat"; + Uri contentUri = new Uri.Builder().authority(context.getPackageName() + ".MmsFileProvider").path(str2).scheme("content").build(); // Bundle a3 = C3326a.m16196a(new C8792q("enableGroupMms", true), new C8792q("maxMessageSize", Integer.valueOf(C3664a.m17428d()))); - SmsManager.getDefault().sendMultimediaMessage(context, contentUri, phoneNumber, null, null); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "sendMmsMessage()", "Error in sendMmsMessage(): " + Log.getStackTraceString(e), 3); - } - } + SmsManager.getDefault().sendMultimediaMessage(context, contentUri, phoneNumber, null, null); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "sendMmsMessage()", "Error in sendMmsMessage(): " + Log.getStackTraceString(e), 3); + } + } - private static class WakeUpDeviceClass implements Runnable - { - private long awakeTime; + private static class WakeUpDeviceClass implements Runnable + { + private long awakeTime; - public WakeUpDeviceClass(long awakeTime) - { - super(); - this.awakeTime = awakeTime; - } + public WakeUpDeviceClass(long awakeTime) + { + super(); + this.awakeTime = awakeTime; + } - @Override - public void run() - { - try - { - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - WakeLock wakeLock = pm.newWakeLock((PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock"); - wakeLock.acquire(); + @Override + public void run() + { + try + { + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + WakeLock wakeLock = pm.newWakeLock((PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock"); + wakeLock.acquire(); - try - { - Thread.sleep(awakeTime); - } - catch (InterruptedException e) - { - Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4); - } + try + { + Thread.sleep(awakeTime); + } + catch (InterruptedException e) + { + Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4); + } - wakeLock.release(); - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Wakeup device action", "Error while waking up device: " + Log.getStackTraceString(e), 1); - } - } - } + wakeLock.release(); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Wakeup device action", "Error while waking up device: " + Log.getStackTraceString(e), 1); + } + } + } /*public static void turnOnScreen() { @@ -1381,10 +1382,10 @@ public class Actions wakeLock.acquire(); }*/ - @TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK - public static void turnOffScreen() - { - Miscellaneous.logEvent("i", "Actions", "Turning screen off.", 3); + @TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK + public static void turnOffScreen() + { + Miscellaneous.logEvent("i", "Actions", "Turning screen off.", 3); /*params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON; @@ -1401,20 +1402,20 @@ public class Actions // wakeLock.acquire(); // wakeLock.release(); - lockScreen(); - } + lockScreen(); + } - public static void lockScreen() - { - Miscellaneous.logEvent("i", "Actions", "Locking screen.", 3); + public static void lockScreen() + { + Miscellaneous.logEvent("i", "Actions", "Locking screen.", 3); - // Works, but requires Manifest.permission.BIND_DEVICE_ADMIN + // Works, but requires Manifest.permission.BIND_DEVICE_ADMIN // https://stackoverflow.com/questions/23898406/java-lang-securityexception-no-active-admin-owned-by-uid-10047-for-policy-4-on - DevicePolicyManager deviceManager = (DevicePolicyManager)Miscellaneous.getAnyContext().getSystemService(Context.DEVICE_POLICY_SERVICE); - deviceManager.lockNow(); - } + DevicePolicyManager deviceManager = (DevicePolicyManager) Miscellaneous.getAnyContext().getSystemService(Context.DEVICE_POLICY_SERVICE); + deviceManager.lockNow(); + } - // using root + // using root /*private void turnOffScreen() { try @@ -1438,10 +1439,10 @@ public class Actions } }*/ - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) - @SuppressLint("NewApi") - public static boolean setAirplaneMode(boolean desiredState, boolean toggleActionIfPossible) - { + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + @SuppressLint("NewApi") + public static boolean setAirplaneMode(boolean desiredState, boolean toggleActionIfPossible) + { /* Beginning from SDK Version 17 this may not work anymore. Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, value is unchanged. @@ -1450,465 +1451,465 @@ public class Actions https://stackoverflow.com/questions/7066427/turn-off-airplane-mode-in-android */ - boolean returnValue = false; + boolean returnValue = false; - try - { - boolean isEnabled = ConnectivityReceiver.isAirplaneMode(automationServerRef); + try + { + boolean isEnabled = ConnectivityReceiver.isAirplaneMode(automationServerRef); - if (isEnabled) - Miscellaneous.logEvent("i", "Airplane mode", "Current status is enabled.", 4); - else - Miscellaneous.logEvent("i", "Airplane mode", "Current status is disabled.", 4); + if (isEnabled) + Miscellaneous.logEvent("i", "Airplane mode", "Current status is enabled.", 4); + else + Miscellaneous.logEvent("i", "Airplane mode", "Current status is disabled.", 4); - if (toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "Airplane mode", context.getResources().getString(R.string.toggling), 4); - desiredState = !isEnabled; - } + if (toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "Airplane mode", context.getResources().getString(R.string.toggling), 4); + desiredState = !isEnabled; + } - if (isEnabled != desiredState) - { - int desiredValueInt = 0; + if (isEnabled != desiredState) + { + int desiredValueInt = 0; - if (desiredState) - desiredValueInt = 1; + if (desiredState) + desiredValueInt = 1; - if (Build.VERSION.SDK_INT < 17 || ActivityPermissions.havePermission(Manifest.permission.WRITE_SECURE_SETTINGS, context)) - { - //returnValue = android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, desiredValueInt); + if (Build.VERSION.SDK_INT < 17 || ActivityPermissions.havePermission(Manifest.permission.WRITE_SECURE_SETTINGS, context)) + { + //returnValue = android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, desiredValueInt); - returnValue = android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, desiredValueInt); + returnValue = android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, desiredValueInt); // Intent airplaneIntent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); // airplaneIntent.putExtra("state", desiredState); // context.sendBroadcast(airplaneIntent); - } - else - { - if (desiredState) - { - String[] commands = new String[] - { - "settings put global airplane_mode_on 1", - "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true" - }; - returnValue = executeCommandViaSu(commands); - } - else - { - String[] commands = new String[] - { - "settings put global airplane_mode_on 0", - "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false" - }; - returnValue = executeCommandViaSu(commands); - } + } + else + { + if (desiredState) + { + String[] commands = new String[] + { + "settings put global airplane_mode_on 1", + "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true" + }; + returnValue = executeCommandViaSu(commands); + } + else + { + String[] commands = new String[] + { + "settings put global airplane_mode_on 0", + "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false" + }; + returnValue = executeCommandViaSu(commands); + } // returnValue = android.provider.Settings.Global.putString(context.getContentResolver(), "airplane_mode_on", String.valueOf(desiredValueInt)); - } + } - // Post an intent to reload - Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", !isEnabled); - context.sendBroadcast(intent); - } - else - Miscellaneous.logEvent("i", "Airplane mode", "Airplane mode is already in status " + String.valueOf(desiredState) + ". Nothing to do.", 3); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "Airplane mode", Log.getStackTraceString(e), 2); - } + // Post an intent to reload + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.putExtra("state", !isEnabled); + context.sendBroadcast(intent); + } + else + Miscellaneous.logEvent("i", "Airplane mode", "Airplane mode is already in status " + String.valueOf(desiredState) + ". Nothing to do.", 3); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Airplane mode", Log.getStackTraceString(e), 2); + } - return returnValue; - } + return returnValue; + } - /** - * Toggles the device between the different types of networks. - * Might not work. It seems only system apps are allowed to do this. - */ - public static boolean setNetworkType(int desiredType) - { - Miscellaneous.logEvent("i", "setNetworkType", "Asked to set network type to: " + String.valueOf(desiredType), 3); - if (desiredType > 0) - { - try - { - ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(context.CONNECTIVITY_SERVICE); + /** + * Toggles the device between the different types of networks. + * Might not work. It seems only system apps are allowed to do this. + */ + public static boolean setNetworkType(int desiredType) + { + Miscellaneous.logEvent("i", "setNetworkType", "Asked to set network type to: " + String.valueOf(desiredType), 3); + if (desiredType > 0) + { + try + { + ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(context.CONNECTIVITY_SERVICE); - // TelephonyManager.NETWORK_TYPE_EDGE + // TelephonyManager.NETWORK_TYPE_EDGE - if (connManager.getNetworkPreference() == desiredType) - { - Miscellaneous.logEvent("i", "setNetworkType", "Desired networkType already set. Not doing anything.", 4); - } - else - { - Miscellaneous.logEvent("i", "setNetworkType", "Setting network type to: " + String.valueOf(desiredType), 3); - connManager.setNetworkPreference(desiredType); - } - return true; - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "setNetworkType", "Error changing network type: " + Log.getStackTraceString(e), 2); - return false; - } - } - else - { - Miscellaneous.logEvent("w", "setNetworkType", "Invalid type of network specified: " + String.valueOf(desiredType), 4); - return false; - } - } + if (connManager.getNetworkPreference() == desiredType) + { + Miscellaneous.logEvent("i", "setNetworkType", "Desired networkType already set. Not doing anything.", 4); + } + else + { + Miscellaneous.logEvent("i", "setNetworkType", "Setting network type to: " + String.valueOf(desiredType), 3); + connManager.setNetworkPreference(desiredType); + } + return true; + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "setNetworkType", "Error changing network type: " + Log.getStackTraceString(e), 2); + return false; + } + } + else + { + Miscellaneous.logEvent("w", "setNetworkType", "Invalid type of network specified: " + String.valueOf(desiredType), 4); + return false; + } + } - public static void speakText(String parameter2) - { - try - { - String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context); - automationServerRef.speak(textToSpeak, true); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "Speak text", "Error in speak text: " + Log.getStackTraceString(e), 3); - } - } + public static void speakText(String parameter2) + { + try + { + String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context); + automationServerRef.speak(textToSpeak, true); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "Speak text", "Error in speak text: " + Log.getStackTraceString(e), 3); + } + } - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) - public static boolean playMusic(boolean desiredState, boolean toggleActionIfPossible) - { - try - { - //TODO:toggle - // if(desiredState) - // { - Miscellaneous.logEvent("e", "Play music", "Starting music player...", 3); + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) + public static boolean playMusic(boolean desiredState, boolean toggleActionIfPossible) + { + try + { + //TODO:toggle + // if(desiredState) + // { + Miscellaneous.logEvent("e", "Play music", "Starting music player...", 3); - String deviceName = Build.MODEL; - /* - * Fix for Samsung devices: http://stackoverflow.com/questions/12532207/open-music-player-on-galaxy-s3 - */ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 | deviceName.contains("SM-")) - playMusicIntent = new Intent(Intent.CATEGORY_APP_MUSIC); - else - playMusicIntent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER); + String deviceName = Build.MODEL; + /* + * Fix for Samsung devices: http://stackoverflow.com/questions/12532207/open-music-player-on-galaxy-s3 + */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 | deviceName.contains("SM-")) + playMusicIntent = new Intent(Intent.CATEGORY_APP_MUSIC); + else + playMusicIntent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER); - playMusicIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(playMusicIntent); + playMusicIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(playMusicIntent); - return true; - } - catch (ActivityNotFoundException e) - { - Toast.makeText(context, "Error: No music player found.", Toast.LENGTH_LONG).show(); - Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): No music player found. " + Log.getStackTraceString(e), 3); - return false; - } - catch (Exception e) - { - Toast.makeText(context, "Error starting music player.", Toast.LENGTH_LONG).show(); - Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): " + Log.getStackTraceString(e), 3); - return false; - } - } + return true; + } + catch (ActivityNotFoundException e) + { + Toast.makeText(context, "Error: No music player found.", Toast.LENGTH_LONG).show(); + Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): No music player found. " + Log.getStackTraceString(e), 3); + return false; + } + catch (Exception e) + { + Toast.makeText(context, "Error starting music player.", Toast.LENGTH_LONG).show(); + Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): " + Log.getStackTraceString(e), 3); + return false; + } + } - @RequiresApi(api = Build.VERSION_CODES.KITKAT) - public static boolean controlMediaPlayback(Context context, int command) - { - int keyCode = -1; - switch(command) - { - case 0: - keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; - break; - case 1: - keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; - break; - case 2: - keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE; - break; - case 3: - keyCode = KeyEvent.KEYCODE_MEDIA_STOP; - break; - case 4: - keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; - break; - case 5: - keyCode = KeyEvent.KEYCODE_MEDIA_NEXT; - break; - } + @RequiresApi(api = Build.VERSION_CODES.KITKAT) + public static boolean controlMediaPlayback(Context context, int command) + { + int keyCode = -1; + switch (command) + { + case 0: + keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; + break; + case 1: + keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; + break; + case 2: + keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE; + break; + case 3: + keyCode = KeyEvent.KEYCODE_MEDIA_STOP; + break; + case 4: + keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; + break; + case 5: + keyCode = KeyEvent.KEYCODE_MEDIA_NEXT; + break; + } - return controlMediaByDispatch(keyCode); - } + return controlMediaByDispatch(keyCode); + } - @RequiresApi(api = Build.VERSION_CODES.KITKAT) - static boolean controlMediaByDispatch(int keyCode) - { - AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); - mAudioManager.dispatchMediaKeyEvent(event); + @RequiresApi(api = Build.VERSION_CODES.KITKAT) + static boolean controlMediaByDispatch(int keyCode) + { + AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); + mAudioManager.dispatchMediaKeyEvent(event); - return true; - } + return true; + } - private String getTransactionCode() - { - try - { - TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - Class telephonyManagerClass = Class.forName(telephonyManager.getClass().getName()); - Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony"); - getITelephonyMethod.setAccessible(true); - Object ITelephonyStub = getITelephonyMethod.invoke(telephonyManager); - Class ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName()); + private String getTransactionCode() + { + try + { + TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + Class telephonyManagerClass = Class.forName(telephonyManager.getClass().getName()); + Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony"); + getITelephonyMethod.setAccessible(true); + Object ITelephonyStub = getITelephonyMethod.invoke(telephonyManager); + Class ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName()); - Class stub = ITelephonyClass.getDeclaringClass(); - Field field = stub.getDeclaredField("TRANSACTION_setDataEnabled"); - field.setAccessible(true); - return String.valueOf(field.getInt(null)); - } - catch (Exception e) - { - if (Build.VERSION.SDK_INT >= 22) - return "86"; - else if (Build.VERSION.SDK_INT == 21) - return "83"; - } - return ""; - } + Class stub = ITelephonyClass.getDeclaringClass(); + Field field = stub.getDeclaredField("TRANSACTION_setDataEnabled"); + field.setAccessible(true); + return String.valueOf(field.getInt(null)); + } + catch (Exception e) + { + if (Build.VERSION.SDK_INT >= 22) + return "86"; + else if (Build.VERSION.SDK_INT == 21) + return "83"; + } + return ""; + } - private static String getTransactionCodeFromApi20(Context context) throws Exception - { - try - { - final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - final Class mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName()); - final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony"); - mTelephonyMethod.setAccessible(true); - final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager); - final Class mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName()); - final Class mClass = mTelephonyStubClass.getDeclaringClass(); - final Field field = mClass.getDeclaredField("TRANSACTION_setDataEnabled"); - field.setAccessible(true); - return String.valueOf(field.getInt(null)); - } - catch (Exception e) - { - // The "TRANSACTION_setDataEnabled" field is not available, - // or named differently in the current API level, so we throw - // an exception and inform users that the method is not available. - throw e; - } - } + private static String getTransactionCodeFromApi20(Context context) throws Exception + { + try + { + final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + final Class mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName()); + final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony"); + mTelephonyMethod.setAccessible(true); + final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager); + final Class mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName()); + final Class mClass = mTelephonyStubClass.getDeclaringClass(); + final Field field = mClass.getDeclaredField("TRANSACTION_setDataEnabled"); + field.setAccessible(true); + return String.valueOf(field.getInt(null)); + } + catch (Exception e) + { + // The "TRANSACTION_setDataEnabled" field is not available, + // or named differently in the current API level, so we throw + // an exception and inform users that the method is not available. + throw e; + } + } - public static class MobileDataStuff - { - // https://stackoverflow.com/questions/31120082/latest-update-on-enabling-and-disabling-mobile-data-programmatically + public static class MobileDataStuff + { + // https://stackoverflow.com/questions/31120082/latest-update-on-enabling-and-disabling-mobile-data-programmatically - /** - * Turns data on and off. - * Requires root permissions from lollipop on. - * - * @param toggleActionIfPossible - */ - public static boolean setDataConnection(boolean desiredState, boolean toggleActionIfPossible) - { - Miscellaneous.logEvent("i", "setData", "Asked to turn data to: " + String.valueOf(desiredState), 3); + /** + * Turns data on and off. + * Requires root permissions from lollipop on. + * + * @param toggleActionIfPossible + */ + public static boolean setDataConnection(boolean desiredState, boolean toggleActionIfPossible) + { + Miscellaneous.logEvent("i", "setData", "Asked to turn data to: " + String.valueOf(desiredState), 3); - try - { - ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(Miscellaneous.getAnyContext().CONNECTIVITY_SERVICE); - final Class conmanClass = Class.forName(connManager.getClass().getName()); - final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); - iConnectivityManagerField.setAccessible(true); - final Object iConnectivityManager = iConnectivityManagerField.get(connManager); - final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); + try + { + ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(Miscellaneous.getAnyContext().CONNECTIVITY_SERVICE); + final Class conmanClass = Class.forName(connManager.getClass().getName()); + final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); + iConnectivityManagerField.setAccessible(true); + final Object iConnectivityManager = iConnectivityManagerField.get(connManager); + final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); - Boolean isEnabled = isMobileDataEnabled(); + Boolean isEnabled = isMobileDataEnabled(); - if (toggleActionIfPossible) - { - context.getResources().getString(R.string.toggling); - desiredState = !isEnabled; - } + if (toggleActionIfPossible) + { + context.getResources().getString(R.string.toggling); + desiredState = !isEnabled; + } - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) - { - for (Method m : iConnectivityManagerClass.getDeclaredMethods()) - { - Miscellaneous.logEvent("i", "method", m.getName(), 5); - } + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) + { + for (Method m : iConnectivityManagerClass.getDeclaredMethods()) + { + Miscellaneous.logEvent("i", "method", m.getName(), 5); + } - final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE); - setMobileDataEnabledMethod.setAccessible(true); + final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE); + setMobileDataEnabledMethod.setAccessible(true); - setMobileDataEnabledMethod.invoke(iConnectivityManager, desiredState); - } - else - { - return setDataConnectionWithRoot(desiredState); - } + setMobileDataEnabledMethod.invoke(iConnectivityManager, desiredState); + } + else + { + return setDataConnectionWithRoot(desiredState); + } - return true; - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "setData", "Error changing network type: " + Log.getStackTraceString(e), 2); - return false; - } - } + return true; + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "setData", "Error changing network type: " + Log.getStackTraceString(e), 2); + return false; + } + } - protected static boolean setDataConnectionWithRoot(boolean desiredState) - { - try - { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - { - if(MobileDataStuff.setMobileNetworkFromAndroid9(desiredState, automationServerRef)) - { - Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); - return true; - } - else - { - Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); - return false; - } - } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - { - if (MobileDataStuff.setMobileNetworkAndroid6Till8(desiredState, automationServerRef)) - { - Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); - return true; - } - else - { - Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); - return false; - } - } - else - { - if (MobileDataStuff.setMobileNetworkTillAndroid5(desiredState, automationServerRef)) - { - Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); - return true; - } - else - { - Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); - return false; - } - } - } - catch (Exception e) - { - String rootString; - if (Miscellaneous.isPhoneRooted()) - rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsRooted); - else - rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsNotRooted); + protected static boolean setDataConnectionWithRoot(boolean desiredState) + { + try + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + { + if (MobileDataStuff.setMobileNetworkFromAndroid9(desiredState, automationServerRef)) + { + Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); + return true; + } + else + { + Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); + return false; + } + } + else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + { + if (MobileDataStuff.setMobileNetworkAndroid6Till8(desiredState, automationServerRef)) + { + Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); + return true; + } + else + { + Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); + return false; + } + } + else + { + if (MobileDataStuff.setMobileNetworkTillAndroid5(desiredState, automationServerRef)) + { + Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); + return true; + } + else + { + Miscellaneous.logEvent("e", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootFail), 2); + return false; + } + } + } + catch (Exception e) + { + String rootString; + if (Miscellaneous.isPhoneRooted()) + rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsRooted); + else + rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsNotRooted); - Miscellaneous.logEvent("e", "setDataWithRoot()", "Error setting data setting with root. " + rootString + ": " + Log.getStackTraceString(e), 3); - } + Miscellaneous.logEvent("e", "setDataWithRoot()", "Error setting data setting with root. " + rootString + ": " + Log.getStackTraceString(e), 3); + } - return false; - } + return false; + } - @SuppressLint("NewApi") - public static boolean setMobileNetworkAndroid6Till8(boolean desiredState, Context context) throws Exception - { - String command = null; + @SuppressLint("NewApi") + public static boolean setMobileNetworkAndroid6Till8(boolean desiredState, Context context) throws Exception + { + String command = null; - try - { - int desiredStateString; - if(desiredState) - desiredStateString = 1; - else - desiredStateString = 0; + try + { + int desiredStateString; + if (desiredState) + desiredStateString = 1; + else + desiredStateString = 0; - // Get the current state of the mobile network. + // Get the current state of the mobile network. // boolean state = isMobileDataEnabled() ? 0 : 1; - // Get the value of the "TRANSACTION_setDataEnabled" field. - String transactionCode = getTransactionCode(context); - // Android 5.1+ (API 22) and later. - SubscriptionManager mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - // Loop through the subscription list i.e. SIM list. - for (int i = 0; i < mSubscriptionManager.getActiveSubscriptionInfoCountMax(); i++) - { - if (transactionCode != null && transactionCode.length() > 0) - { - // Get the active subscription ID for a given SIM card. - int subscriptionId = mSubscriptionManager.getActiveSubscriptionInfoList().get(i).getSubscriptionId(); - // Execute the command via `su` to turn off - // mobile network for a subscription service. - command = "service call phone " + transactionCode + " i32 " + subscriptionId + " i32 " + desiredStateString; - Miscellaneous.logEvent("i", "setMobileNetworkAndroid6Till8()", "Running command: " + command.toString(), 5); - return executeCommandViaSu(new String[]{command}); - } - } - } - catch (Exception e) - { - // Oops! Something went wrong, so we throw the exception here. - throw e; - } + // Get the value of the "TRANSACTION_setDataEnabled" field. + String transactionCode = getTransactionCode(context); + // Android 5.1+ (API 22) and later. + SubscriptionManager mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); + // Loop through the subscription list i.e. SIM list. + for (int i = 0; i < mSubscriptionManager.getActiveSubscriptionInfoCountMax(); i++) + { + if (transactionCode != null && transactionCode.length() > 0) + { + // Get the active subscription ID for a given SIM card. + int subscriptionId = mSubscriptionManager.getActiveSubscriptionInfoList().get(i).getSubscriptionId(); + // Execute the command via `su` to turn off + // mobile network for a subscription service. + command = "service call phone " + transactionCode + " i32 " + subscriptionId + " i32 " + desiredStateString; + Miscellaneous.logEvent("i", "setMobileNetworkAndroid6Till8()", "Running command: " + command.toString(), 5); + return executeCommandViaSu(new String[]{command}); + } + } + } + catch (Exception e) + { + // Oops! Something went wrong, so we throw the exception here. + throw e; + } - return false; - } + return false; + } - @SuppressLint("NewApi") - public static boolean setMobileNetworkTillAndroid5(boolean desiredState, Context context) throws Exception - { - String command = null; + @SuppressLint("NewApi") + public static boolean setMobileNetworkTillAndroid5(boolean desiredState, Context context) throws Exception + { + String command = null; - try - { - int desiredStateString; - if(desiredState) - desiredStateString = 1; - else - desiredStateString = 0; + try + { + int desiredStateString; + if (desiredState) + desiredStateString = 1; + else + desiredStateString = 0; - // Get the current state of the mobile network. + // Get the current state of the mobile network. // int currentState = isMobileDataEnabled() ? 0 : 1; - // Get the value of the "TRANSACTION_setDataEnabled" field. - String transactionCode = getTransactionCode(context); - // Android 5.0 (API 21) only. - if (transactionCode != null && transactionCode.length() > 0) - { - // Execute the command via `su` to turn off mobile network. - command = "service call phone " + transactionCode + " i32 " + desiredStateString; - Miscellaneous.logEvent("i", "setMobileNetworkTillAndroid5()", "Running command: " + command.toString(), 5); - return executeCommandViaSu(new String[]{command}); - } - } - catch (Exception e) - { - // Oops! Something went wrong, so we throw the exception here. - throw e; - } + // Get the value of the "TRANSACTION_setDataEnabled" field. + String transactionCode = getTransactionCode(context); + // Android 5.0 (API 21) only. + if (transactionCode != null && transactionCode.length() > 0) + { + // Execute the command via `su` to turn off mobile network. + command = "service call phone " + transactionCode + " i32 " + desiredStateString; + Miscellaneous.logEvent("i", "setMobileNetworkTillAndroid5()", "Running command: " + command.toString(), 5); + return executeCommandViaSu(new String[]{command}); + } + } + catch (Exception e) + { + // Oops! Something went wrong, so we throw the exception here. + throw e; + } - return false; - } + return false; + } - @SuppressLint("NewApi") - public static boolean setMobileNetworkFromAndroid9(boolean desiredState, Context context) throws Exception - { - String command = null; + @SuppressLint("NewApi") + public static boolean setMobileNetworkFromAndroid9(boolean desiredState, Context context) throws Exception + { + String command = null; - String desiredStateString; - if(desiredState) - desiredStateString = "enable"; - else - desiredStateString = "disable"; + String desiredStateString; + if (desiredState) + desiredStateString = "enable"; + else + desiredStateString = "disable"; - try - { + try + { /* Android 8.1 is the last version on which the transaction code can be determined with the below method. From 9.0 on the field TRANSACTION_setDataEnabled does not @@ -1917,143 +1918,143 @@ public class Actions https://stackoverflow.com/questions/26539445/the-setmobiledataenabled-method-is-no-longer-callable-as-of-android-l-and-later */ - // Execute the command via `su` to turn off - // mobile network for a subscription service. - command = "svc data " + desiredStateString; - Miscellaneous.logEvent("i", "setMobileNetworkFromAndroid9()", "Running command: " + command.toString(), 5); - return executeCommandViaSu(new String[]{command}); - } - catch (Exception e) - { - // Oops! Something went wrong, so we throw the exception here. - throw e; - } - } + // Execute the command via `su` to turn off + // mobile network for a subscription service. + command = "svc data " + desiredStateString; + Miscellaneous.logEvent("i", "setMobileNetworkFromAndroid9()", "Running command: " + command.toString(), 5); + return executeCommandViaSu(new String[]{command}); + } + catch (Exception e) + { + // Oops! Something went wrong, so we throw the exception here. + throw e; + } + } - @SuppressLint("NewApi") - public static boolean isMobileDataEnabled() - { - boolean isEnabled = false; + @SuppressLint("NewApi") + public static boolean isMobileDataEnabled() + { + boolean isEnabled = false; - if (Build.VERSION.SDK_INT <= 20) - { - try - { - ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(Miscellaneous.getAnyContext().CONNECTIVITY_SERVICE); - final Class conmanClass = Class.forName(connManager.getClass().getName()); - final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); - iConnectivityManagerField.setAccessible(true); - final Object iConnectivityManager = iConnectivityManagerField.get(connManager); - final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); + if (Build.VERSION.SDK_INT <= 20) + { + try + { + ConnectivityManager connManager = (ConnectivityManager) Miscellaneous.getAnyContext().getSystemService(Miscellaneous.getAnyContext().CONNECTIVITY_SERVICE); + final Class conmanClass = Class.forName(connManager.getClass().getName()); + final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); + iConnectivityManagerField.setAccessible(true); + final Object iConnectivityManager = iConnectivityManagerField.get(connManager); + final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); - Method getMobileDataEnabledMethod = null; - for (Method m : iConnectivityManagerClass.getDeclaredMethods()) - { - Miscellaneous.logEvent("i", "Methods", m.getName(), 5); - if (m.getName().equals("getMobileDataEnabled")) - { - getMobileDataEnabledMethod = m; - break; - } - } - // final Method getMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("getMobileDataEnabled", null); + Method getMobileDataEnabledMethod = null; + for (Method m : iConnectivityManagerClass.getDeclaredMethods()) + { + Miscellaneous.logEvent("i", "Methods", m.getName(), 5); + if (m.getName().equals("getMobileDataEnabled")) + { + getMobileDataEnabledMethod = m; + break; + } + } + // final Method getMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("getMobileDataEnabled", null); - getMobileDataEnabledMethod.setAccessible(true); + getMobileDataEnabledMethod.setAccessible(true); - isEnabled = (Boolean) getMobileDataEnabledMethod.invoke(iConnectivityManager, (Object[]) null); - } - catch (Exception e) - { - Miscellaneous.logEvent("e", "isMobileDataEnabled()", "Error checking if mobile data is enabled: " + Log.getStackTraceString(e), 3); - } - } - else - { - isEnabled = android.provider.Settings.Global.getInt(context.getContentResolver(), "mobile_data", 0) == 1; - } + isEnabled = (Boolean) getMobileDataEnabledMethod.invoke(iConnectivityManager, (Object[]) null); + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "isMobileDataEnabled()", "Error checking if mobile data is enabled: " + Log.getStackTraceString(e), 3); + } + } + else + { + isEnabled = android.provider.Settings.Global.getInt(context.getContentResolver(), "mobile_data", 0) == 1; + } - return isEnabled; - } + return isEnabled; + } - private static String getTransactionCode(Context context) throws Exception - { - try - { - final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - final Class mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName()); - final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony"); - mTelephonyMethod.setAccessible(true); - final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager); - final Class mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName()); - final Class mClass = mTelephonyStubClass.getDeclaringClass(); - final Field field = mClass.getDeclaredField("TRANSACTION_setDataEnabled"); - field.setAccessible(true); - return String.valueOf(field.getInt(null)); - } - catch (Exception e) - { - // The "TRANSACTION_setDataEnabled" field is not available, - // or named differently in the current API level, so we throw - // an exception and inform users that the method is not available. - throw e; - } - } - } + private static String getTransactionCode(Context context) throws Exception + { + try + { + final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + final Class mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName()); + final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony"); + mTelephonyMethod.setAccessible(true); + final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager); + final Class mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName()); + final Class mClass = mTelephonyStubClass.getDeclaringClass(); + final Field field = mClass.getDeclaredField("TRANSACTION_setDataEnabled"); + field.setAccessible(true); + return String.valueOf(field.getInt(null)); + } + catch (Exception e) + { + // The "TRANSACTION_setDataEnabled" field is not available, + // or named differently in the current API level, so we throw + // an exception and inform users that the method is not available. + throw e; + } + } + } - protected static boolean executeCommandViaSu(String[] commands) - { - boolean suAvailable = false; - String suVersion = null; - String suVersionInternal = null; - int suResult; + protected static boolean executeCommandViaSu(String[] commands) + { + boolean suAvailable = false; + String suVersion = null; + String suVersionInternal = null; + int suResult; - boolean success = false; + boolean success = false; - try - { - suAvailable = Shell.SU.available(); - if (suAvailable) - { - suVersion = Shell.SU.version(false); - suVersionInternal = Shell.SU.version(true); + try + { + suAvailable = Shell.SU.available(); + if (suAvailable) + { + suVersion = Shell.SU.version(false); + suVersionInternal = Shell.SU.version(true); - Miscellaneous.logEvent("i", "executeCommandViaSu()", "suVersion: " + suVersion + ", suVersionInternal: " + suVersionInternal, 5); - Miscellaneous.logEvent("i", "executeCommandViaSu()", "calling method: " + Miscellaneous.getCallingMethodName(), 5); + Miscellaneous.logEvent("i", "executeCommandViaSu()", "suVersion: " + suVersion + ", suVersionInternal: " + suVersionInternal, 5); + Miscellaneous.logEvent("i", "executeCommandViaSu()", "calling method: " + Miscellaneous.getCallingMethodName(), 5); - suResult = Shell.Pool.SU.run(commands); + suResult = Shell.Pool.SU.run(commands); - if(Miscellaneous.getCallingMethodName().equals("runExecutable")) - { - Actions.setVariable("last_run_executable_exit_code" + Action.actionParameter2Split + String.valueOf(suResult)); + if (Miscellaneous.getCallingMethodName().equals("runExecutable")) + { + Actions.setVariable("last_run_executable_exit_code" + Action.actionParameter2Split + String.valueOf(suResult)); // Actions.setVariable("last_run_executable_output" + Action.actionParameter2Split + (String) result[1]); - } + } - Miscellaneous.logEvent("i", "executeCommandViaSu()", "RC=" + String.valueOf(suResult), 3); + Miscellaneous.logEvent("i", "executeCommandViaSu()", "RC=" + String.valueOf(suResult), 3); - if(suResult == 0) - success = true; - } - else - Miscellaneous.logEvent("w", "executeCommandViaSu()", "su not available.", 4); - } - catch (Exception e) - { - success = false; - } + if (suResult == 0) + success = true; + } + else + Miscellaneous.logEvent("w", "executeCommandViaSu()", "su not available.", 4); + } + catch (Exception e) + { + success = false; + } - Miscellaneous.logEvent("i", "executeCommandViaSu()", "Returning " + String.valueOf(success), 4); + Miscellaneous.logEvent("i", "executeCommandViaSu()", "Returning " + String.valueOf(success), 4); - return success; - } + return success; + } - public static void setScreenBrightness(boolean autoBrightness, int brightnessValue) - { - if (autoBrightness) - android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); - else - android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + public static void setScreenBrightness(boolean autoBrightness, int brightnessValue) + { + if (autoBrightness) + android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + else + android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); - // Old mathematical approach doesn't seem to be working anymore + // Old mathematical approach doesn't seem to be working anymore // int actualBrightnessValue = (int) ((float) brightnessValue / 100.0 * 255.0); // try @@ -2070,16 +2071,16 @@ public class Actions // // } - int actualBrightnessValue = getBrightnessSetting(brightnessValue); + int actualBrightnessValue = getBrightnessSetting(brightnessValue); - Miscellaneous.logEvent("i", "Screen brightness", "Setting screen brightness to " + String.valueOf(brightnessValue) + " by using " + String.valueOf(actualBrightnessValue), 4); - android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, actualBrightnessValue); - } + Miscellaneous.logEvent("i", "Screen brightness", "Setting screen brightness to " + String.valueOf(brightnessValue) + " by using " + String.valueOf(actualBrightnessValue), 4); + android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, actualBrightnessValue); + } - static int getBrightnessSetting(int percentage) - { - if(percentage == 0) - return 1; // seems to be the minimum, 0 isn't working + static int getBrightnessSetting(int percentage) + { + if (percentage == 0) + return 1; // seems to be the minimum, 0 isn't working /* By taking notes which value results in which brightness percentage I came up with this lookup list. @@ -2088,489 +2089,489 @@ public class Actions Not all percentages can be implemented. Hence the next possible value will be used. */ - Map percentageSettingValueMap = new HashMap<>(); + Map percentageSettingValueMap = new HashMap<>(); - if(Build.VERSION.SDK_INT < 34) - { - // Noted from Android 10 - percentageSettingValueMap.put(11, 10); - percentageSettingValueMap.put(16, 11); - percentageSettingValueMap.put(19, 12); - percentageSettingValueMap.put(22, 13); - percentageSettingValueMap.put(25, 14); - percentageSettingValueMap.put(27, 15); - percentageSettingValueMap.put(29, 16); - percentageSettingValueMap.put(31, 17); - percentageSettingValueMap.put(33, 18); - percentageSettingValueMap.put(35, 19); - percentageSettingValueMap.put(37, 20); - percentageSettingValueMap.put(38, 21); - percentageSettingValueMap.put(40, 22); - percentageSettingValueMap.put(41, 23); - percentageSettingValueMap.put(43, 24); - percentageSettingValueMap.put(44, 25); - percentageSettingValueMap.put(46, 26); - percentageSettingValueMap.put(47, 27); - percentageSettingValueMap.put(48, 28); - percentageSettingValueMap.put(49, 29); - percentageSettingValueMap.put(51, 30); - percentageSettingValueMap.put(52, 31); - percentageSettingValueMap.put(53, 32); - percentageSettingValueMap.put(54, 33); - percentageSettingValueMap.put(55, 34); - percentageSettingValueMap.put(56, 35); - percentageSettingValueMap.put(57, 36); - percentageSettingValueMap.put(58, 38); - percentageSettingValueMap.put(59, 39); - percentageSettingValueMap.put(60, 40); - percentageSettingValueMap.put(61, 42); - percentageSettingValueMap.put(62, 43); - percentageSettingValueMap.put(63, 45); - percentageSettingValueMap.put(64, 46); - percentageSettingValueMap.put(65, 48); - percentageSettingValueMap.put(66, 50); - percentageSettingValueMap.put(67, 52); - percentageSettingValueMap.put(68, 54); - percentageSettingValueMap.put(69, 56); - percentageSettingValueMap.put(70, 59); - percentageSettingValueMap.put(71, 61); - percentageSettingValueMap.put(72, 64); - percentageSettingValueMap.put(73, 67); - percentageSettingValueMap.put(74, 70); - percentageSettingValueMap.put(75, 73); - percentageSettingValueMap.put(76, 76); - percentageSettingValueMap.put(77, 80); - percentageSettingValueMap.put(78, 84); - percentageSettingValueMap.put(79, 87); - percentageSettingValueMap.put(80, 91); - percentageSettingValueMap.put(81, 96); - percentageSettingValueMap.put(82, 100); - percentageSettingValueMap.put(83, 105); - percentageSettingValueMap.put(84, 111); - percentageSettingValueMap.put(85, 116); - percentageSettingValueMap.put(86, 122); - percentageSettingValueMap.put(87, 128); - percentageSettingValueMap.put(88, 134); - percentageSettingValueMap.put(89, 141); - percentageSettingValueMap.put(90, 148); - percentageSettingValueMap.put(91, 156); - percentageSettingValueMap.put(92, 164); - percentageSettingValueMap.put(93, 173); - percentageSettingValueMap.put(94, 182); - percentageSettingValueMap.put(95, 191); - percentageSettingValueMap.put(96, 201); - percentageSettingValueMap.put(97, 212); - percentageSettingValueMap.put(98, 223); - percentageSettingValueMap.put(99, 235); - percentageSettingValueMap.put(100, 247); - } - else - { - // Noted from Android 14 - percentageSettingValueMap.put(11,1); - percentageSettingValueMap.put(15,2); - percentageSettingValueMap.put(19,3); - percentageSettingValueMap.put(22,4); - percentageSettingValueMap.put(24,5); - percentageSettingValueMap.put(27,6); - percentageSettingValueMap.put(29,7); - percentageSettingValueMap.put(31,8); - percentageSettingValueMap.put(33,9); - percentageSettingValueMap.put(34,10); - percentageSettingValueMap.put(36,11); - percentageSettingValueMap.put(38,12); - percentageSettingValueMap.put(39,13); - percentageSettingValueMap.put(41,14); - percentageSettingValueMap.put(42,15); - percentageSettingValueMap.put(43,16); - percentageSettingValueMap.put(45,17); - percentageSettingValueMap.put(46,18); - percentageSettingValueMap.put(47,47); - percentageSettingValueMap.put(48,49); - percentageSettingValueMap.put(50,21); - percentageSettingValueMap.put(51,22); - percentageSettingValueMap.put(52,23); - percentageSettingValueMap.put(53,24); - percentageSettingValueMap.put(54,25); - percentageSettingValueMap.put(55,26); - percentageSettingValueMap.put(56,27); - percentageSettingValueMap.put(57,28); - percentageSettingValueMap.put(58,30); - percentageSettingValueMap.put(59,31); - percentageSettingValueMap.put(60,32); - percentageSettingValueMap.put(61,34); - percentageSettingValueMap.put(62,35); - percentageSettingValueMap.put(63,37); - percentageSettingValueMap.put(64,39); - percentageSettingValueMap.put(65,41); - percentageSettingValueMap.put(66,43); - percentageSettingValueMap.put(67,45); - percentageSettingValueMap.put(68,47); - percentageSettingValueMap.put(69,49); - percentageSettingValueMap.put(70,52); - percentageSettingValueMap.put(71,54); - percentageSettingValueMap.put(72,57); - percentageSettingValueMap.put(73,60); - percentageSettingValueMap.put(74,63); - percentageSettingValueMap.put(75,66); - percentageSettingValueMap.put(76,70); - percentageSettingValueMap.put(77,73); - percentageSettingValueMap.put(78,77); - percentageSettingValueMap.put(79,81); - percentageSettingValueMap.put(80,85); - percentageSettingValueMap.put(81,90); - percentageSettingValueMap.put(82,95); - percentageSettingValueMap.put(83,100); - percentageSettingValueMap.put(84,105); - percentageSettingValueMap.put(85,111); - percentageSettingValueMap.put(86,117); - percentageSettingValueMap.put(87,124); - percentageSettingValueMap.put(88,130); - percentageSettingValueMap.put(89,137); - percentageSettingValueMap.put(90,144); - percentageSettingValueMap.put(91,152); - percentageSettingValueMap.put(92,161); - percentageSettingValueMap.put(93,170); - percentageSettingValueMap.put(94,179); - percentageSettingValueMap.put(95,189); - percentageSettingValueMap.put(96,199); - percentageSettingValueMap.put(97,210); - percentageSettingValueMap.put(98,223); - percentageSettingValueMap.put(99,235); - percentageSettingValueMap.put(100,248); - } + if (Build.VERSION.SDK_INT < 34) + { + // Noted from Android 10 + percentageSettingValueMap.put(11, 10); + percentageSettingValueMap.put(16, 11); + percentageSettingValueMap.put(19, 12); + percentageSettingValueMap.put(22, 13); + percentageSettingValueMap.put(25, 14); + percentageSettingValueMap.put(27, 15); + percentageSettingValueMap.put(29, 16); + percentageSettingValueMap.put(31, 17); + percentageSettingValueMap.put(33, 18); + percentageSettingValueMap.put(35, 19); + percentageSettingValueMap.put(37, 20); + percentageSettingValueMap.put(38, 21); + percentageSettingValueMap.put(40, 22); + percentageSettingValueMap.put(41, 23); + percentageSettingValueMap.put(43, 24); + percentageSettingValueMap.put(44, 25); + percentageSettingValueMap.put(46, 26); + percentageSettingValueMap.put(47, 27); + percentageSettingValueMap.put(48, 28); + percentageSettingValueMap.put(49, 29); + percentageSettingValueMap.put(51, 30); + percentageSettingValueMap.put(52, 31); + percentageSettingValueMap.put(53, 32); + percentageSettingValueMap.put(54, 33); + percentageSettingValueMap.put(55, 34); + percentageSettingValueMap.put(56, 35); + percentageSettingValueMap.put(57, 36); + percentageSettingValueMap.put(58, 38); + percentageSettingValueMap.put(59, 39); + percentageSettingValueMap.put(60, 40); + percentageSettingValueMap.put(61, 42); + percentageSettingValueMap.put(62, 43); + percentageSettingValueMap.put(63, 45); + percentageSettingValueMap.put(64, 46); + percentageSettingValueMap.put(65, 48); + percentageSettingValueMap.put(66, 50); + percentageSettingValueMap.put(67, 52); + percentageSettingValueMap.put(68, 54); + percentageSettingValueMap.put(69, 56); + percentageSettingValueMap.put(70, 59); + percentageSettingValueMap.put(71, 61); + percentageSettingValueMap.put(72, 64); + percentageSettingValueMap.put(73, 67); + percentageSettingValueMap.put(74, 70); + percentageSettingValueMap.put(75, 73); + percentageSettingValueMap.put(76, 76); + percentageSettingValueMap.put(77, 80); + percentageSettingValueMap.put(78, 84); + percentageSettingValueMap.put(79, 87); + percentageSettingValueMap.put(80, 91); + percentageSettingValueMap.put(81, 96); + percentageSettingValueMap.put(82, 100); + percentageSettingValueMap.put(83, 105); + percentageSettingValueMap.put(84, 111); + percentageSettingValueMap.put(85, 116); + percentageSettingValueMap.put(86, 122); + percentageSettingValueMap.put(87, 128); + percentageSettingValueMap.put(88, 134); + percentageSettingValueMap.put(89, 141); + percentageSettingValueMap.put(90, 148); + percentageSettingValueMap.put(91, 156); + percentageSettingValueMap.put(92, 164); + percentageSettingValueMap.put(93, 173); + percentageSettingValueMap.put(94, 182); + percentageSettingValueMap.put(95, 191); + percentageSettingValueMap.put(96, 201); + percentageSettingValueMap.put(97, 212); + percentageSettingValueMap.put(98, 223); + percentageSettingValueMap.put(99, 235); + percentageSettingValueMap.put(100, 247); + } + else + { + // Noted from Android 14 + percentageSettingValueMap.put(11, 1); + percentageSettingValueMap.put(15, 2); + percentageSettingValueMap.put(19, 3); + percentageSettingValueMap.put(22, 4); + percentageSettingValueMap.put(24, 5); + percentageSettingValueMap.put(27, 6); + percentageSettingValueMap.put(29, 7); + percentageSettingValueMap.put(31, 8); + percentageSettingValueMap.put(33, 9); + percentageSettingValueMap.put(34, 10); + percentageSettingValueMap.put(36, 11); + percentageSettingValueMap.put(38, 12); + percentageSettingValueMap.put(39, 13); + percentageSettingValueMap.put(41, 14); + percentageSettingValueMap.put(42, 15); + percentageSettingValueMap.put(43, 16); + percentageSettingValueMap.put(45, 17); + percentageSettingValueMap.put(46, 18); + percentageSettingValueMap.put(47, 47); + percentageSettingValueMap.put(48, 49); + percentageSettingValueMap.put(50, 21); + percentageSettingValueMap.put(51, 22); + percentageSettingValueMap.put(52, 23); + percentageSettingValueMap.put(53, 24); + percentageSettingValueMap.put(54, 25); + percentageSettingValueMap.put(55, 26); + percentageSettingValueMap.put(56, 27); + percentageSettingValueMap.put(57, 28); + percentageSettingValueMap.put(58, 30); + percentageSettingValueMap.put(59, 31); + percentageSettingValueMap.put(60, 32); + percentageSettingValueMap.put(61, 34); + percentageSettingValueMap.put(62, 35); + percentageSettingValueMap.put(63, 37); + percentageSettingValueMap.put(64, 39); + percentageSettingValueMap.put(65, 41); + percentageSettingValueMap.put(66, 43); + percentageSettingValueMap.put(67, 45); + percentageSettingValueMap.put(68, 47); + percentageSettingValueMap.put(69, 49); + percentageSettingValueMap.put(70, 52); + percentageSettingValueMap.put(71, 54); + percentageSettingValueMap.put(72, 57); + percentageSettingValueMap.put(73, 60); + percentageSettingValueMap.put(74, 63); + percentageSettingValueMap.put(75, 66); + percentageSettingValueMap.put(76, 70); + percentageSettingValueMap.put(77, 73); + percentageSettingValueMap.put(78, 77); + percentageSettingValueMap.put(79, 81); + percentageSettingValueMap.put(80, 85); + percentageSettingValueMap.put(81, 90); + percentageSettingValueMap.put(82, 95); + percentageSettingValueMap.put(83, 100); + percentageSettingValueMap.put(84, 105); + percentageSettingValueMap.put(85, 111); + percentageSettingValueMap.put(86, 117); + percentageSettingValueMap.put(87, 124); + percentageSettingValueMap.put(88, 130); + percentageSettingValueMap.put(89, 137); + percentageSettingValueMap.put(90, 144); + percentageSettingValueMap.put(91, 152); + percentageSettingValueMap.put(92, 161); + percentageSettingValueMap.put(93, 170); + percentageSettingValueMap.put(94, 179); + percentageSettingValueMap.put(95, 189); + percentageSettingValueMap.put(96, 199); + percentageSettingValueMap.put(97, 210); + percentageSettingValueMap.put(98, 223); + percentageSettingValueMap.put(99, 235); + percentageSettingValueMap.put(100, 248); + } - if(percentageSettingValueMap.containsKey(percentage)) - return percentageSettingValueMap.get(percentage); - else - { - // Find next best value - for(int i = percentage; i <= 100; i++) - { - if(percentageSettingValueMap.containsKey(i)) - return percentageSettingValueMap.get(i); - } - } + if (percentageSettingValueMap.containsKey(percentage)) + return percentageSettingValueMap.get(percentage); + else + { + // Find next best value + for (int i = percentage; i <= 100; i++) + { + if (percentageSettingValueMap.containsKey(i)) + return percentageSettingValueMap.get(i); + } + } - return 0; - } + return 0; + } - public boolean isAirplaneModeOn(Context context) - { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) - { - return android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, 0) != 0; - } - else - { - return android.provider.Settings.Global.getInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - } - } + public boolean isAirplaneModeOn(Context context) + { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) + { + return android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, 0) != 0; + } + else + { + 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; + 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()); + 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); + if (!StringUtils.isEmpty(parameters)) + result = runExternalApplication(path, 0, workingDir, parameters); + else + result = runExternalApplication(path, 0, workingDir, null); - boolean execResult = ((int) result[0] == 0); + boolean execResult = ((int) result[0] == 0); - Actions.setVariable("last_run_executable_exit_code" + Action.actionParameter2Split + String.valueOf((int) result[0])); - Actions.setVariable("last_run_executable_output" + Action.actionParameter2Split + (String) result[1]); + Actions.setVariable("last_run_executable_exit_code" + Action.actionParameter2Split + String.valueOf((int) result[0])); + Actions.setVariable("last_run_executable_output" + Action.actionParameter2Split + (String) result[1]); - return execResult; - } - } + 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 - */ + /** + * @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; + String fullCommand; - if(!StringUtils.isEmpty(params)) - fullCommand = commandToExecute + " " + params; - else - fullCommand = commandToExecute; + if (!StringUtils.isEmpty(params)) + fullCommand = commandToExecute + " " + params; + else + fullCommand = commandToExecute; - Miscellaneous.logEvent("i", "Running executable", "Running external application " + fullCommand, 4); + Miscellaneous.logEvent("i", "Running executable", "Running external application " + fullCommand, 4); - Object[] returnObject = new Object[2]; + Object[] returnObject = new Object[2]; - StringBuilder output = new StringBuilder(); - String line = null; - OutputStream stdin = null; - InputStream stderr = null; - InputStream stdout = null; + StringBuilder output = new StringBuilder(); + String line = null; + OutputStream stdin = null; + InputStream stderr = null; + InputStream stdout = null; - try - { - Process process = 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 (); + 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(); - stdin.close(); + 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 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(); + // 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); - } + 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); + 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(); + returnObject[0] = process.exitValue(); + returnObject[1] = output.toString(); - return returnObject; - } - catch (IOException e) - { - Miscellaneous.logEvent("e", "Running executable", Log.getStackTraceString(e), 1); - } + return returnObject; + } + catch (IOException e) + { + Miscellaneous.logEvent("e", "Running executable", Log.getStackTraceString(e), 1); + } - Miscellaneous.logEvent("i", "Running executable", "Error running external application.", 1); + Miscellaneous.logEvent("i", "Running executable", "Error running external application.", 1); - return null; - } + return null; + } - public static boolean isTetheringActive1(Context context) - { - try - { - for(Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) - { - NetworkInterface intf = en.nextElement(); + 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(); + 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); - } + if (!intf.isLoopback()) + { + if (intf.getName().contains("rndis")) + { + return true; + } + } + } + } + } + catch (Exception e) + { + Miscellaneous.logEvent("e", "isTetheringActive()", Log.getStackTraceString(e), 3); + } - return false; - } + return false; + } - public final static int wakeLockTimeoutDisabled = -1; - static boolean wakeLockStopRequested = false; - public static void wakeLockStart(Context context, long duration) - { - Thread lockThread = new Thread(new Runnable() - { - @Override - public void run() - { - wakeLockStopRequested = false; + public final static int wakeLockTimeoutDisabled = -1; + static boolean wakeLockStopRequested = false; - long waited = 0; - int step = 2000; + public static void wakeLockStart(Context context, long duration) + { + Thread lockThread = new Thread(new Runnable() + { + @Override + public void run() + { + wakeLockStopRequested = false; - try - { - PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK"); - fullWakeLock.acquire(); // turn on + long waited = 0; + int step = 2000; - do - { + try + { + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK"); + fullWakeLock.acquire(); // turn on - try - { - Thread.sleep(step); // turn on duration - } - catch (InterruptedException e) - { - e.printStackTrace(); - } + do + { - if(duration > 0) - waited += step; + try + { + Thread.sleep(step); // turn on duration + } + catch (InterruptedException e) + { + e.printStackTrace(); + } - if(wakeLockStopRequested) //stop requested - Miscellaneous.logEvent("i", "WakeLockStart", "Stop requested.", 4); - } - while(!wakeLockStopRequested && (duration < 0 || waited <= duration)); + if (duration > 0) + waited += step; - fullWakeLock.release(); - } - catch (Exception e) - { - } - } - }); + if (wakeLockStopRequested) //stop requested + Miscellaneous.logEvent("i", "WakeLockStart", "Stop requested.", 4); + } + while (!wakeLockStopRequested && (duration < 0 || waited <= duration)); - lockThread.start(); - } + fullWakeLock.release(); + } + catch (Exception e) + { + } + } + }); - public static void wakeLockStop() - { - Miscellaneous.logEvent("i", "WakeLockStart", "Requesting stop.", 4); - wakeLockStopRequested = true; - } + lockThread.start(); + } - public static void startPhoneCall(Context context, String phoneNumber) - { - Intent intent; + public static void wakeLockStop() + { + Miscellaneous.logEvent("i", "WakeLockStart", "Requesting stop.", 4); + wakeLockStopRequested = true; + } + + public static void startPhoneCall(Context context, String phoneNumber) + { + Intent intent; /* Bug in Android 14 makes it necessary to add double quotes around MMI code. More precisely it's required for codes containing the # character. */ - if(Build.VERSION.SDK_INT >= 34) - intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode("\"" + phoneNumber + "\""))); - else - intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode(phoneNumber))); + if (Build.VERSION.SDK_INT >= 34) + intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode("\"" + phoneNumber + "\""))); + else + intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode(phoneNumber))); // intent.setClassName("com.android.phone","com.android.phone.OutgoingCallBroadcaster"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addFlags(Intent.FLAG_FROM_BACKGROUND); - context.startActivity(intent); - } + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_FROM_BACKGROUND); + context.startActivity(intent); + } - public static void endPhoneCall(Context context) - { - if(Build.VERSION.SDK_INT < 21) - { - TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - try - { - Class c = Class.forName(tm.getClass().getName()); - Method m = c.getDeclaredMethod("getITelephony"); - m.setAccessible(true); - Object telephonyService = m.invoke(tm); + public static void endPhoneCall(Context context) + { + if (Build.VERSION.SDK_INT < 21) + { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + try + { + Class c = Class.forName(tm.getClass().getName()); + Method m = c.getDeclaredMethod("getITelephony"); + m.setAccessible(true); + Object telephonyService = m.invoke(tm); - c = Class.forName(telephonyService.getClass().getName()); - m = c.getDeclaredMethod("endCall"); - m.setAccessible(true); - m.invoke(telephonyService); + c = Class.forName(telephonyService.getClass().getName()); + m = c.getDeclaredMethod("endCall"); + m.setAccessible(true); + m.invoke(telephonyService); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - else - { - TelecomManager mgr = (TelecomManager) context.getSystemService(context.TELECOM_SERVICE); - mgr.endCall(); - } - } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + else + { + TelecomManager mgr = (TelecomManager) context.getSystemService(context.TELECOM_SERVICE); + mgr.endCall(); + } + } - public static void copyToClipboard(Context context, String text) - { - Miscellaneous.logEvent("i", "Clipboard", "Copying data to clipboard: " + text, 4); + public static void copyToClipboard(Context context, String text) + { + Miscellaneous.logEvent("i", "Clipboard", "Copying data to clipboard: " + text, 4); - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) - { - android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setText(text); - } - else - { - android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - android.content.ClipData clip = android.content.ClipData.newPlainText("Data-from-Automation", text); - clipboard.setPrimaryClip(clip); - } - } + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) + { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText(text); + } + else + { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("Data-from-Automation", text); + clipboard.setPrimaryClip(clip); + } + } - public static void takeScreenshot() - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - { - if(!BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay)) - MyAccessibilityService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT); - } - } + public static void takeScreenshot() + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + { + if (!BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay)) + MyAccessibilityService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT); + } + } - public static void setLocationService(int desiredState, Context context) - { + public static void setLocationService(int desiredState, Context context) + { // if(desiredState) // { // android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, new Integer(android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY).toString()); @@ -2579,7 +2580,7 @@ public class Actions // { // android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, new Integer(android.provider.Settings.Secure.LOCATION_MODE_OFF).toString()); // } - android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, String.valueOf(desiredState)); - } + android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, String.valueOf(desiredState)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java index f6985d5..d7966dc 100644 --- a/app/src/main/java/com/jens/automation2/ActivityMainScreen.java +++ b/app/src/main/java/com/jens/automation2/ActivityMainScreen.java @@ -11,6 +11,7 @@ import android.content.res.Resources; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.text.method.LinkMovementMethod; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; @@ -46,7 +47,7 @@ public class ActivityMainScreen extends ActivityGeneric ToggleButton toggleService, tbLockSound; Button bShowHelp, bPrivacy, bAddSoundLockTIme, bDonate, bControlCenter; - TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration; + TextView tvActivePoi, tvClosestPoi, tvLastRule, tvLastProfile, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvLockSoundDuration, tvContactNotice; ListView lvRuleHistory; ArrayAdapter ruleHistoryListViewAdapter; @@ -83,10 +84,14 @@ public class ActivityMainScreen extends ActivityGeneric tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound); toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener); bDonate = (Button)findViewById(R.id.bDonate); + tvContactNotice = (TextView) findViewById(R.id.tvContactNotice); if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay)) bDonate.setVisibility(View.VISIBLE); + // Make links clickable + tvContactNotice.setMovementMethod(LinkMovementMethod.getInstance()); + toggleService.setChecked(AutomationService.isMyServiceRunning(this)); toggleService.setOnCheckedChangeListener(new OnCheckedChangeListener() { diff --git a/app/src/main/java/com/jens/automation2/AutomationService.java b/app/src/main/java/com/jens/automation2/AutomationService.java index 93df10f..4b266d6 100644 --- a/app/src/main/java/com/jens/automation2/AutomationService.java +++ b/app/src/main/java/com/jens/automation2/AutomationService.java @@ -157,6 +157,15 @@ public class AutomationService extends Service implements OnInitListener ActivityPermissions.requestSpecificPermission(Manifest.permission.FOREGROUND_SERVICE); return false; } + else + { + if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34 && !ActivityPermissions.havePermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, context)) + { + Toast.makeText(context, context.getResources().getString(R.string.permissionForegroundServiceTypeSpecialUseRequired), Toast.LENGTH_LONG).show(); + Miscellaneous.logEvent("e", "Permission", "Don't have permission FOREGROUND_SERVICE_SPECIAL_USE. Will request it now.", 4); + return false; + } + } } if ( @@ -510,6 +519,7 @@ public class AutomationService extends Service implements OnInitListener { Intent myServiceIntent = new Intent(context, AutomationService.class); myServiceIntent.putExtra("startAtBoot", startAtBoot); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(myServiceIntent); else @@ -661,9 +671,9 @@ public class AutomationService extends Service implements OnInitListener myNotification.flags |= Notification.FLAG_NO_CLEAR; // notificationManager.notify(notificationId, myNotification); - if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34) - instance.startForeground(notificationId, myNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE); - else +// if(Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 34) +// instance.startForeground(notificationId, myNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE); +// else instance.startForeground(notificationId, myNotification); } } diff --git a/app/src/main/res/layout/main_overview_layout.xml b/app/src/main/res/layout/main_overview_layout.xml index 32129c9..6f798c1 100644 --- a/app/src/main/res/layout/main_overview_layout.xml +++ b/app/src/main/res/layout/main_overview_layout.xml @@ -370,11 +370,12 @@ android:text="@string/donate" /> + android:text="@string/contactNotice" /> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9298008..43621ec 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -698,7 +698,7 @@ Bildschirm ist %1$s Email an Entwickler schicken Steuerungszentrale - Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.\nViele Fragen können nicht einfach gleich beantwortet werden, sondern erfordern eine technische Prüfung. Haben Sie also bitte etwas Geduld. + Email ist mein bevorzugtes Kommunikationsmittel, um Fehler zu melden, Fragen zu stellen or Vorschläge zu machen. Bitte gehen Sie für weitere Infos in die Steuerungszentrale.\nViele Fragen können nicht einfach gleich beantwortet werden, sondern erfordern eine technische Prüfung. Haben Sie also bitte etwas Geduld.\n\nAlternativ können Sie Ihre Frage im Forum stellen. Aufgrund Google\'s unendlicher Weisheit, ist die letzte Android Version, mit der diese Funktion noch funktioniert, die Version %1$s. Sie können es hier einrichten, aber vermutlich wird es keine Auswirkung haben. Musik läuft Wählen Sie die Parameter diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index beaf2e2..704d6db 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -697,7 +697,7 @@ pantalla esta %1$s Enviar email al desrollador Debido a la infinita sabiduría de Google, la última versión de Android en la que se sabe que funciona esta función es %1$s. Puede configurarlo, pero probablemente no tendrá ningún efecto. - El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.\nMuchas preguntas no se pueden responder de inmediato, pero requieren cierta investigación técnica. Así que, por favor, tengan un poco de paciencia. + El correo electrónico es mi método preferido de contacto para informar errores, hacer preguntas o hacer propuestas. Vaya al centro de control para obtener más información.\nMuchas preguntas no se pueden responder de inmediato, pero requieren cierta investigación técnica. Así que, por favor, tengan un poco de paciencia. \n\nAlternativamente, tiene la opción de hacer sus preguntas en el foro. Ten en cuenta que esta acción puede no funcionar con TODOS los jugadores. E incluso si lo hace, no todos los botones funcionan necesariamente. Musica esta reproduciendo Elije parametros diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 82684f8..65a9ee6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -679,7 +679,7 @@ La coparaisonn est sensible à la casse du texte Les paramètres que vous pouvez régler ici affectent les évènements audio sur votre télephone. Ils peuvent même annuler votre alarme de réveil. Donc, quoi que vous fassiez, il est fortement recommandé de le tester, même après les mises à jour d’Android. si - L’e-mail est mon moyen de contact préféré pour signaler les bogues, poser des questions ou faire des propositions. Rendez-vous sur le centre de contrôle pour en savoir plus. Des questions multiples peuvent ne pas recevoir de réponse immédiate, mais nécessitent des recherches techniques. Veuillez donc faire preuve de patience. + L’e-mail est mon moyen de contact préféré pour signaler les bogues, poser des questions ou faire des propositions. Rendez-vous sur le centre de contrôle pour en savoir plus. Des questions multiples peuvent ne pas recevoir de réponse immédiate, mais nécessitent des recherches techniques. Veuillez donc faire preuve de patience. \n\nSinon, vous avez la possibilité de poser vos questions dans le forum. Centre de contrôle Envoyer un email au développeur l’écran est %1$s diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index bf9204f..6870bbd 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -699,7 +699,7 @@ lo schermo è %1$s Invia email allo sviluppatore Centro di controllo - L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.\nMolte domande non possono essere risolte immediatamente, ma richiedono alcune ricerche tecniche. Quindi, per favore, abbiate un po\' di pazienza. + L\'e-mail è il mio metodo di contatto preferito per segnalare bug, porre domande o fare proposte. Vai al centro di controllo per saperne di più.\nMolte domande non possono essere risolte immediatamente, ma richiedono alcune ricerche tecniche. Quindi, per favore, abbiate un po\' di pazienza. \n\nIn alternativa hai la possibilità di porre le tue domande nel forum. La musica è in riproduzione la musica è in riproduzione la musica non viene riprodotta diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b8818e4..3def5d0 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -677,7 +677,7 @@ Vergelijkingen worden gedaan case-INsensitief De instellingen die je hier maakt kunnen ervoor zorgen dat je bepaalde dingen niet meer van je telefoon merkt. Ze kunnen zelfs je wekker dempen. Dus wat je ook doet - het wordt aanbevolen om het te testen - ook na Android upgrades. als - E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.\nVeel vragen kunnen niet meteen worden beantwoord, maar vereisen wel wat technisch onderzoek. Dus heb alsjeblieft wat geduld. + E-mail is mijn favoriete contactmethode om bugs te melden, vragen te stellen of voorstellen te doen. Ga naar het controlecentrum voor meer informatie.\nVeel vragen kunnen niet meteen worden beantwoord, maar vereisen wel wat technisch onderzoek. Dus heb alsjeblieft wat geduld. \n\nJe hebt ook de mogelijkheid om je vragen te stellen in het forum. Controlecentrum Stuur een e-mail naar de ontwikkelaar scherm is %1$s diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 936997a..839f825 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -769,7 +769,7 @@ Porównania nie uwzględniają wielkości liter Ustawienia, które możesz tutaj dostosować, mogą sprawić, że nie będziesz już zauważać pewnych rzeczy w swoim telefonie. Mogą nawet wyciszyć budzik. Więc cokolwiek robisz - zdecydowanie zalecamy przetestowanie tego - także po aktualizacjach Androida. jeśli - E-mail to moja preferowana metoda kontaktu w celu zgłaszania błędów, zadawania pytań lub składania propozycji. Przejdź do centrum sterowania, aby dowiedzieć się więcej.\nNa wiele pytań nie można odpowiedzieć od razu, ale wymagają one pewnych działań technicznych. Prosimy więc o odrobinę cierpliwości. + E-mail to moja preferowana metoda kontaktu w celu zgłaszania błędów, zadawania pytań lub składania propozycji. Przejdź do centrum sterowania, aby dowiedzieć się więcej.\nNa wiele pytań nie można odpowiedzieć od razu, ale wymagają one pewnych działań technicznych. Prosimy więc o odrobinę cierpliwości. \n\nAlternatywnie masz możliwość zadawania pytań na forum. Centrum kontroli Wyślij wiadomość e-mail do programisty ekran to %1$s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 6bdd14c..b2bb8a0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -736,7 +736,7 @@ Сравнения проводятся без учета регистра Настройки, которые вы можете изменить здесь, могут привести к тому, что вы больше не заметите определенных вещей с вашего телефона. Они могут даже отключить будильник. Так что что бы вы ни делали - рекомендуется это проверять. если - Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.\nМногие вопросы не могут быть решены сразу, но требуют некоторых технических исследований. Поэтому, пожалуйста, наберитесь терпения. + Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.\nМногие вопросы не могут быть решены сразу, но требуют некоторых технических исследований. Поэтому, пожалуйста, наберитесь терпения. \n\nВ качестве альтернативы у вас есть возможность задать свои вопросы на форуме. Центр управления Отправить электронное письмо разработчику экран %1$s diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 28a2244..5a685dc 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -671,7 +671,7 @@ 比较不区分大小写 此处的设置可能会导致您无法再注意到手机中的某些内容,甚至可以让您的起床闹钟静音。所以无论怎样设置——强烈建议测试,在 Android 更新之后也要再测试。 如果 - 电子邮件是向我报告错误、提出问题或建议的首选联系方式。前往控制中心了解更多信息。\n许多问题无法立即解答,需要进行一些技术研究。所以请耐心等待。 + 电子邮件是向我报告错误、提出问题或建议的首选联系方式。前往控制中心了解更多信息。\n许多问题无法立即解答,需要进行一些技术研究。所以请耐心等待。 \n\n或者,您可以选择在 论坛中提问 。 控制中心 向开发者发送电子邮件 屏幕 %1$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e096dd9..f1f2553 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -770,7 +770,7 @@ Comparisons are done case-INsensitive The settings you can adjust here, can cause that you don\'t notice certain things from your phone anymore. They may even silence your wakeup alarm. So whatever you do - it is highly recommended that you test it - also after Android updates. if - Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.\nMany questions cannot be answered straight away, but require some technical research. So please have some patience. + Email is my preferred method of contact to report bugs, ask questions or make proposals. Go to control center to learn more.\nMany questions cannot be answered straight away, but require some technical research. So please have some patience.\n\nAlternatively you have the option of asking your questions in the forum. Control center Send email to developer screen is %1$s diff --git a/fastlane/metadata/android/en-US/changelogs/145.txt b/fastlane/metadata/android/en-US/changelogs/145.txt new file mode 100644 index 0000000..7666153 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/145.txt @@ -0,0 +1 @@ +* Fixed: Crash in Play Store version when starting the service \ No newline at end of file