Wifi tethering without root above Oreo works again.

This commit is contained in:
jens 2021-05-30 20:03:30 +02:00
parent f22e4854ee
commit 21ee06e9b1
12 changed files with 489 additions and 450 deletions

View File

@ -1,5 +1,6 @@
package com.jens.automation2; package com.jens.automation2;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -71,24 +72,24 @@ public class Actions
{ {
Miscellaneous.logEvent("i", "Wifi", "Changing Wifi to " + String.valueOf(desiredState), 4); Miscellaneous.logEvent("i", "Wifi", "Changing Wifi to " + String.valueOf(desiredState), 4);
if(desiredState && Settings.useWifiForPositioning) if (desiredState && Settings.useWifiForPositioning)
WifiBroadcastReceiver.startWifiReceiver(autoMationServerRef.getLocationProvider()); WifiBroadcastReceiver.startWifiReceiver(autoMationServerRef.getLocationProvider());
WifiManager myWifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); WifiManager myWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// toggle // toggle
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Toast.makeText(context, context.getResources().getString(R.string.toggling) + " " + context.getResources().getString(R.string.wifi), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.toggling) + " " + context.getResources().getString(R.string.wifi), Toast.LENGTH_LONG).show();
desiredState = !myWifi.isWifiEnabled(); desiredState = !myWifi.isWifiEnabled();
} }
// Only perform action if necessary // Only perform action if necessary
if((!myWifi.isWifiEnabled() && desiredState) | (myWifi.isWifiEnabled() && !desiredState)) if ((!myWifi.isWifiEnabled() && desiredState) | (myWifi.isWifiEnabled() && !desiredState))
{ {
String wifiString = ""; String wifiString = "";
if(desiredState) if (desiredState)
{ {
wifiString = context.getResources().getString(R.string.activating) + " " + context.getResources().getString(R.string.wifi); wifiString = context.getResources().getString(R.string.activating) + " " + context.getResources().getString(R.string.wifi);
} }
@ -100,7 +101,7 @@ public class Actions
Toast.makeText(context, wifiString, Toast.LENGTH_LONG).show(); Toast.makeText(context, wifiString, Toast.LENGTH_LONG).show();
boolean returnValue = myWifi.setWifiEnabled(desiredState); boolean returnValue = myWifi.setWifiEnabled(desiredState);
if(!returnValue) if (!returnValue)
Miscellaneous.logEvent("i", "Wifi", "Error changing Wifi to " + String.valueOf(desiredState), 2); Miscellaneous.logEvent("i", "Wifi", "Error changing Wifi to " + String.valueOf(desiredState), 2);
else else
Miscellaneous.logEvent("i", "Wifi", "Wifi changed to " + String.valueOf(desiredState), 2); Miscellaneous.logEvent("i", "Wifi", "Wifi changed to " + String.valueOf(desiredState), 2);
@ -116,19 +117,19 @@ public class Actions
Miscellaneous.logEvent("i", "ScreenRotation", "Changing ScreenRotation to " + String.valueOf(desiredState), 4); Miscellaneous.logEvent("i", "ScreenRotation", "Changing ScreenRotation to " + String.valueOf(desiredState), 4);
try try
{ {
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.toggling), 2); 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; boolean currentStatus = android.provider.Settings.System.getInt(myContext.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0;
if(currentStatus) if (currentStatus)
desiredState = !currentStatus; desiredState = !currentStatus;
} }
if(desiredState) if (desiredState)
{ {
if(android.provider.Settings.System.getInt(myContext.getContentResolver(),android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 0) 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); 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); Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationEnabled), 2);
} }
else else
@ -136,16 +137,16 @@ public class Actions
} }
else else
{ {
if(android.provider.Settings.System.getInt(myContext.getContentResolver(),android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 1) 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); 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); Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationDisabled), 2);
} }
else else
Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyDisabled), 2); Miscellaneous.logEvent("i", "setScreenRotation", myContext.getResources().getString(R.string.screenRotationAlreadyDisabled), 2);
} }
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "setScreenRotation", myContext.getResources().getString(R.string.errorChangingScreenRotation) + ": " + Log.getStackTraceString(e), 2); Miscellaneous.logEvent("e", "setScreenRotation", myContext.getResources().getString(R.string.errorChangingScreenRotation) + ": " + Log.getStackTraceString(e), 2);
} }
@ -153,25 +154,25 @@ public class Actions
private static boolean isWifiApEnabled(Context context) private static boolean isWifiApEnabled(Context context)
{ {
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
boolean currentlyEnabled = false; boolean currentlyEnabled = false;
Method[] methods = wifiManager.getClass().getDeclaredMethods(); Method[] methods = wifiManager.getClass().getDeclaredMethods();
for(Method method : methods) for (Method method : methods)
{ {
if(method.getName().equals("isWifiApEnabled")) if (method.getName().equals("isWifiApEnabled"))
{ {
try try
{ {
Object returnObject = method.invoke(wifiManager); Object returnObject = method.invoke(wifiManager);
currentlyEnabled = Boolean.valueOf(returnObject.toString()); currentlyEnabled = Boolean.valueOf(returnObject.toString());
if(currentlyEnabled) if (currentlyEnabled)
Miscellaneous.logEvent("i", "isWifiApEnabled", "true", 5); Miscellaneous.logEvent("i", "isWifiApEnabled", "true", 5);
else else
Miscellaneous.logEvent("i", "isWifiApEnabled", "false", 5); Miscellaneous.logEvent("i", "isWifiApEnabled", "false", 5);
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("i", "isWifiApEnabled", context.getResources().getString(R.string.errorDeterminingWifiApState) + ": " + e.getMessage(), 4); Miscellaneous.logEvent("i", "isWifiApEnabled", context.getResources().getString(R.string.errorDeterminingWifiApState) + ": " + e.getMessage(), 4);
} }
@ -179,21 +180,22 @@ public class Actions
} }
return currentlyEnabled; return currentlyEnabled;
} }
public static Boolean setWifiTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible) public static Boolean setWifiTethering(Context context, Boolean desiredState, boolean toggleActionIfPossible)
{ {
Miscellaneous.logEvent("i", "WifiTethering", "Changing WifiTethering to " + String.valueOf(desiredState), 4); Miscellaneous.logEvent("i", "WifiTethering", "Changing WifiTethering to " + String.valueOf(desiredState), 4);
boolean state = Actions.isWifiApEnabled(context); boolean state = Actions.isWifiApEnabled(context);
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.toggling), 2); Miscellaneous.logEvent("i", "WifiAp", context.getResources().getString(R.string.toggling), 2);
desiredState = !state; desiredState = !state;
} }
if(((state && !desiredState) || (!state && desiredState))) if (((state && !desiredState) || (!state && desiredState)))
{ {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
{ {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Method[] methods = wifiManager.getClass().getDeclaredMethods(); Method[] methods = wifiManager.getClass().getDeclaredMethods();
@ -252,7 +254,7 @@ public class Actions
}; };
MyOreoWifiManager mowm = new MyOreoWifiManager(context); MyOreoWifiManager mowm = new MyOreoWifiManager(context);
if(desiredState) if (desiredState)
mowm.startTethering(cb); mowm.startTethering(cb);
else else
mowm.stopTethering(); mowm.stopTethering();
@ -274,9 +276,9 @@ public class Actions
try try
{ {
connectivityServiceObject = context.getSystemService(Context.CONNECTIVITY_SERVICE); connectivityServiceObject = context.getSystemService(Context.CONNECTIVITY_SERVICE);
connMgr = (ConnectivityManager)connectivityServiceObject; connMgr = (ConnectivityManager) connectivityServiceObject;
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "UsbTethering", context2.getResources().getString(R.string.logErrorGettingConnectionManagerService), 2); Miscellaneous.logEvent("e", "UsbTethering", context2.getResources().getString(R.string.logErrorGettingConnectionManagerService), 2);
return false; return false;
@ -284,18 +286,18 @@ public class Actions
try try
{ {
if((state && !desiredState) || (!state && desiredState)) if ((state && !desiredState) || (!state && desiredState))
{ {
try try
{ {
Method method = connectivityServiceObject.getClass().getDeclaredMethod("getTetheredIfaces"); Method method = connectivityServiceObject.getClass().getDeclaredMethod("getTetheredIfaces");
if(!method.isAccessible()) if (!method.isAccessible())
method.setAccessible(true); method.setAccessible(true);
String[] tetheredInterfaces = (String[]) method.invoke(connectivityServiceObject); String[] tetheredInterfaces = (String[]) method.invoke(connectivityServiceObject);
if(tetheredInterfaces.length > 0) if (tetheredInterfaces.length > 0)
state = true; state = true;
} }
catch(NoSuchMethodException e) catch (NoSuchMethodException e)
{ {
// System doesn't have that method, try another way // System doesn't have that method, try another way
@ -307,22 +309,22 @@ public class Actions
} }
} }
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.logErrorDeterminingCurrentUsbTetheringState), 3); Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.logErrorDeterminingCurrentUsbTetheringState), 3);
} }
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.toggling), 3); Miscellaneous.logEvent("w", "UsbTethering", context2.getResources().getString(R.string.toggling), 3);
desiredState = !state; desiredState = !state;
} }
if((state && !desiredState) || (!state && desiredState)) if ((state && !desiredState) || (!state && desiredState))
{ {
String desiredString = ""; String desiredString = "";
if(desiredState) if (desiredState)
desiredString = "activate"; desiredString = "activate";
else else
desiredString = "deactivate"; desiredString = "deactivate";
@ -331,22 +333,22 @@ public class Actions
{ {
Method method = null; Method method = null;
for(Method m : connectivityServiceObject.getClass().getDeclaredMethods()) for (Method m : connectivityServiceObject.getClass().getDeclaredMethods())
{ {
if(desiredState && m.getName().equals("tether")) if (desiredState && m.getName().equals("tether"))
{ {
method = m; method = m;
break; break;
} }
if(!desiredState && m.getName().equals("untether")) if (!desiredState && m.getName().equals("untether"))
{ {
method = m; method = m;
break; break;
} }
} }
if(method == null) if (method == null)
throw new NoSuchMethodException(); throw new NoSuchMethodException();
@ -362,13 +364,13 @@ public class Actions
Miscellaneous.logEvent("i", "UsbTethering", context2.getResources().getString(R.string.logDetectingTetherableUsbInterface), 4); Miscellaneous.logEvent("i", "UsbTethering", context2.getResources().getString(R.string.logDetectingTetherableUsbInterface), 4);
String[] available = null; String[] available = null;
Method[] wmMethods = connMgr.getClass().getDeclaredMethods(); Method[] wmMethods = connMgr.getClass().getDeclaredMethods();
for(Method getMethod: wmMethods) for (Method getMethod : wmMethods)
{ {
if(getMethod.getName().equals("getTetherableUsbRegexs")) if (getMethod.getName().equals("getTetherableUsbRegexs"))
{ {
try try
{ {
if(!method.isAccessible()) if (!method.isAccessible())
method.setAccessible(true); method.setAccessible(true);
available = (String[]) getMethod.invoke(connMgr); available = (String[]) getMethod.invoke(connMgr);
// break; // break;
@ -382,16 +384,16 @@ public class Actions
// DETECT INTERFACE NAME // DETECT INTERFACE NAME
if(available.length > 0) if (available.length > 0)
{ {
for(String interfaceName : available) for (String interfaceName : available)
{ {
Miscellaneous.logEvent("i", "UsbTethering", "Detected " + String.valueOf(available.length) + " tetherable usb interfaces.", 5); 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); Miscellaneous.logEvent("i", "UsbTethering", "Trying to " + desiredString + " UsbTethering on interface " + interfaceName + "...", 5);
if(!method.isAccessible()) if (!method.isAccessible())
method.setAccessible(true); method.setAccessible(true);
Integer returnCode = (Integer)method.invoke(connectivityServiceObject, interfaceName); Integer returnCode = (Integer) method.invoke(connectivityServiceObject, interfaceName);
if(returnCode == 0) if (returnCode == 0)
{ {
Miscellaneous.logEvent("i", "UsbTethering", "UsbTethering " + desiredString + "d.", 5); Miscellaneous.logEvent("i", "UsbTethering", "UsbTethering " + desiredString + "d.", 5);
return true; return true;
@ -407,7 +409,7 @@ public class Actions
{ {
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); 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) catch (Exception e)
{ {
Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. " + Log.getStackTraceString(e), 3); Miscellaneous.logEvent("w", "UsbTethering", "Error while trying to " + desiredString + " UsbTethering. " + Log.getStackTraceString(e), 3);
} }
@ -424,14 +426,14 @@ public class Actions
BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// toggle // toggle
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.toggling), 2); Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.toggling), 2);
desiredState = !myBluetoothAdapter.isEnabled(); desiredState = !myBluetoothAdapter.isEnabled();
} }
// activate // activate
if(!myBluetoothAdapter.isEnabled() && desiredState) if (!myBluetoothAdapter.isEnabled() && desiredState)
{ {
Toast.makeText(context, context.getResources().getString(R.string.activating) + " Bluetooth.", Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.activating) + " Bluetooth.", Toast.LENGTH_LONG).show();
myBluetoothAdapter.enable(); myBluetoothAdapter.enable();
@ -439,14 +441,14 @@ public class Actions
} }
// deactivate // deactivate
if(myBluetoothAdapter.isEnabled() && !desiredState) if (myBluetoothAdapter.isEnabled() && !desiredState)
{ {
Toast.makeText(context, context.getResources().getString(R.string.deactivating) + " Bluetooth.", Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.deactivating) + " Bluetooth.", Toast.LENGTH_LONG).show();
myBluetoothAdapter.disable(); myBluetoothAdapter.disable();
return true; return true;
} }
} }
catch(NullPointerException e) catch (NullPointerException e)
{ {
Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.failedToTriggerBluetooth), 2); Miscellaneous.logEvent("e", "SetBluetooth", context.getResources().getString(R.string.failedToTriggerBluetooth), 2);
Toast.makeText(context, context.getResources().getString(R.string.bluetoothFailed), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.bluetoothFailed), Toast.LENGTH_LONG).show();
@ -459,7 +461,7 @@ public class Actions
{ {
Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing sound to " + String.valueOf(soundSetting), 4); Miscellaneous.logEvent("i", context.getResources().getString(R.string.soundSettings), "Changing sound to " + String.valueOf(soundSetting), 4);
AudioManager myAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); AudioManager myAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
myAudioManager.setRingerMode(soundSetting); myAudioManager.setRingerMode(soundSetting);
} }
@ -505,13 +507,13 @@ public class Actions
public static void playSound(boolean alwaysPlay, String soundFileLocation) public static void playSound(boolean alwaysPlay, String soundFileLocation)
{ {
if(alwaysPlay || ((AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE)).getRingerMode() == AudioManager.RINGER_MODE_NORMAL) if (alwaysPlay || ((AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE)).getRingerMode() == AudioManager.RINGER_MODE_NORMAL)
{ {
MediaPlayer mp = new MediaPlayer(); MediaPlayer mp = new MediaPlayer();
try try
{ {
File file = new File(soundFileLocation); File file = new File(soundFileLocation);
if(file.exists()) if (file.exists())
{ {
Uri fileUri = Uri.parse(soundFileLocation); Uri fileUri = Uri.parse(soundFileLocation);
mp.setLooping(false); mp.setLooping(false);
@ -611,7 +613,7 @@ public class Actions
int paramsStartIndex; int paramsStartIndex;
if(!startByAction) if (!startByAction)
{ {
// selected by activity // selected by activity
@ -632,7 +634,7 @@ public class Actions
// else // else
externalActivityIntent.setClassName(packageName, className); externalActivityIntent.setClassName(packageName, className);
if(!Miscellaneous.doesActivityExist(externalActivityIntent, Miscellaneous.getAnyContext())) if (!Miscellaneous.doesActivityExist(externalActivityIntent, Miscellaneous.getAnyContext()))
Miscellaneous.logEvent("w", "StartOtherApp", "Activity not found: " + className, 2); Miscellaneous.logEvent("w", "StartOtherApp", "Activity not found: " + className, 2);
} }
else else
@ -642,7 +644,7 @@ public class Actions
externalActivityIntent = new Intent(); externalActivityIntent = new Intent();
if(!params[0].equals(dummyPackageString)) if (!params[0].equals(dummyPackageString))
externalActivityIntent.setPackage(params[0]); externalActivityIntent.setPackage(params[0]);
externalActivityIntent.setAction(params[1]); externalActivityIntent.setAction(params[1]);
@ -712,7 +714,7 @@ public class Actions
} }
else if (singleParam[0].equals("Uri")) else if (singleParam[0].equals("Uri"))
{ {
if(singleParam[1].equalsIgnoreCase("IntentData")) if (singleParam[1].equalsIgnoreCase("IntentData"))
{ {
Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with value " + singleParam[2] + " as standard data parameter.", 3); Miscellaneous.logEvent("i", "StartOtherApp", "Adding parameter of type " + singleParam[0] + " with value " + singleParam[2] + " as standard data parameter.", 3);
externalActivityIntent.setData(Uri.parse(singleParam[2])); externalActivityIntent.setData(Uri.parse(singleParam[2]));
@ -732,12 +734,12 @@ public class Actions
Miscellaneous.logEvent("w", "StartOtherApp", "Unknown type of parameter " + singleParam[0] + " found. Name " + singleParam[1] + " and value " + singleParam[2], 3); Miscellaneous.logEvent("w", "StartOtherApp", "Unknown type of parameter " + singleParam[0] + " found. Name " + singleParam[1] + " and value " + singleParam[2], 3);
} }
if(params[2].equals(ActivityManageActionStartActivity.startByActivityString)) if (params[2].equals(ActivityManageActionStartActivity.startByActivityString))
autoMationServerRef.startActivity(externalActivityIntent); autoMationServerRef.startActivity(externalActivityIntent);
else else
autoMationServerRef.sendBroadcast(externalActivityIntent); autoMationServerRef.sendBroadcast(externalActivityIntent);
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "StartOtherApp", autoMationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + Log.getStackTraceString(e), 2); 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(); Toast.makeText(autoMationServerRef, autoMationServerRef.getResources().getString(R.string.errorStartingOtherActivity) + ": " + e.getMessage(), Toast.LENGTH_LONG).show();
@ -761,12 +763,12 @@ public class Actions
public static void wakeupDevice(Long awakeTime) public static void wakeupDevice(Long awakeTime)
{ {
String duration = "default"; String duration = "default";
if(awakeTime > 0) if (awakeTime > 0)
duration = String.valueOf(awakeTime) + " milliseconds"; 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) if (awakeTime > 0)
{ {
/* /*
* This action needs to be performed in a separate thread. If it ran in the same one * This action needs to be performed in a separate thread. If it ran in the same one
@ -799,7 +801,7 @@ public class Actions
SmsManager sms = SmsManager.getDefault(); SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, pi, null); sms.sendTextMessage(phoneNumber, null, message, pi, null);
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", Miscellaneous.getAnyContext().getString(R.string.sendTextMessage), "Error in sendTextMessage: " + Log.getStackTraceString(e), 3);
} }
@ -839,8 +841,13 @@ public class Actions
@SuppressLint("NewApi") @SuppressLint("NewApi")
public static boolean setAirplaneMode(boolean desiredState, boolean toggleActionIfPossible) 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. 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.
https://stackoverflow.com/questions/22349928/permission-denial-not-allowed-to-send-broadcast-android-intent-action-airplane
https://stackoverflow.com/questions/7066427/turn-off-airplane-mode-in-android
*/
boolean returnValue = false; boolean returnValue = false;
@ -848,31 +855,37 @@ public class Actions
{ {
boolean isEnabled = ConnectivityReceiver.isAirplaneMode(autoMationServerRef); boolean isEnabled = ConnectivityReceiver.isAirplaneMode(autoMationServerRef);
if(isEnabled) if (isEnabled)
Miscellaneous.logEvent("i", "Airplane mode", "Current status is enabled.", 4); Miscellaneous.logEvent("i", "Airplane mode", "Current status is enabled.", 4);
else else
Miscellaneous.logEvent("i", "Airplane mode", "Current status is disabled.", 4); Miscellaneous.logEvent("i", "Airplane mode", "Current status is disabled.", 4);
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
Miscellaneous.logEvent("i", "Airplane mode", context.getResources().getString(R.string.toggling), 4); Miscellaneous.logEvent("i", "Airplane mode", context.getResources().getString(R.string.toggling), 4);
desiredState = !isEnabled; desiredState = !isEnabled;
} }
if(isEnabled != desiredState) if (isEnabled != desiredState)
{ {
int desiredValueInt = 0; int desiredValueInt = 0;
if(desiredState) if (desiredState)
desiredValueInt = 1; desiredValueInt = 1;
if(Build.VERSION.SDK_INT < 17) 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.System.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 else
{ {
if(desiredState) if (desiredState)
{ {
String[] commands = new String[] String[] commands = new String[]
{ {
@ -883,7 +896,6 @@ public class Actions
} }
else else
{ {
String[] commands = new String[] String[] commands = new String[]
{ {
"settings put global airplane_mode_on 0", "settings put global airplane_mode_on 0",
@ -903,7 +915,7 @@ public class Actions
else else
Miscellaneous.logEvent("i", "Airplane mode", "Airplane mode is already in status " + String.valueOf(desiredState) + ". Nothing to do.", 3); Miscellaneous.logEvent("i", "Airplane mode", "Airplane mode is already in status " + String.valueOf(desiredState) + ". Nothing to do.", 3);
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "Airplane mode", Log.getStackTraceString(e), 2); Miscellaneous.logEvent("e", "Airplane mode", Log.getStackTraceString(e), 2);
} }
@ -918,7 +930,7 @@ public class Actions
public static boolean setNetworkType(int desiredType) public static boolean setNetworkType(int desiredType)
{ {
Miscellaneous.logEvent("i", "setNetworkType", "Asked to set network type to: " + String.valueOf(desiredType), 3); Miscellaneous.logEvent("i", "setNetworkType", "Asked to set network type to: " + String.valueOf(desiredType), 3);
if(desiredType > 0) if (desiredType > 0)
{ {
try try
{ {
@ -926,7 +938,7 @@ public class Actions
// TelephonyManager.NETWORK_TYPE_EDGE // TelephonyManager.NETWORK_TYPE_EDGE
if(connManager.getNetworkPreference() == desiredType) if (connManager.getNetworkPreference() == desiredType)
{ {
Miscellaneous.logEvent("i", "setNetworkType", "Desired networkType already set. Not doing anything.", 4); Miscellaneous.logEvent("i", "setNetworkType", "Desired networkType already set. Not doing anything.", 4);
} }
@ -937,7 +949,7 @@ public class Actions
} }
return true; return true;
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "setNetworkType", "Error changing network type: " + Log.getStackTraceString(e), 2); Miscellaneous.logEvent("e", "setNetworkType", "Error changing network type: " + Log.getStackTraceString(e), 2);
return false; return false;
@ -957,7 +969,7 @@ public class Actions
String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context); String textToSpeak = Miscellaneous.replaceVariablesInText(parameter2, context);
autoMationServerRef.speak(textToSpeak, true); autoMationServerRef.speak(textToSpeak, true);
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "Speak text", "Error in speak text: " + Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", "Speak text", "Error in speak text: " + Log.getStackTraceString(e), 3);
} }
@ -977,7 +989,7 @@ public class Actions
/* /*
* Fix for Samsung devices: http://stackoverflow.com/questions/12532207/open-music-player-on-galaxy-s3 * 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-")) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 | deviceName.contains("SM-"))
playMusicIntent = new Intent(Intent.CATEGORY_APP_MUSIC); playMusicIntent = new Intent(Intent.CATEGORY_APP_MUSIC);
else else
playMusicIntent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER); playMusicIntent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER);
@ -1003,13 +1015,13 @@ public class Actions
// return false; // return false;
} }
catch(ActivityNotFoundException e) catch (ActivityNotFoundException e)
{ {
Toast.makeText(context, "Error: No music player found.", Toast.LENGTH_LONG).show(); 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); Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): No music player found. " + Log.getStackTraceString(e), 3);
return false; return false;
} }
catch(Exception e) catch (Exception e)
{ {
Toast.makeText(context, "Error starting music player.", Toast.LENGTH_LONG).show(); Toast.makeText(context, "Error starting music player.", Toast.LENGTH_LONG).show();
Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): " + Log.getStackTraceString(e), 3); Miscellaneous.logEvent("e", "Play music", "Error in playerMusic(): " + Log.getStackTraceString(e), 3);
@ -1074,6 +1086,7 @@ public class Actions
/** /**
* Turns data on and off. * Turns data on and off.
* Requires root permissions from lollipop on. * Requires root permissions from lollipop on.
*
* @param toggleActionIfPossible * @param toggleActionIfPossible
*/ */
public static boolean setDataConnection(boolean desiredState, boolean toggleActionIfPossible) public static boolean setDataConnection(boolean desiredState, boolean toggleActionIfPossible)
@ -1091,15 +1104,15 @@ public class Actions
Boolean isEnabled = isMobileDataEnabled(); Boolean isEnabled = isMobileDataEnabled();
if(toggleActionIfPossible) if (toggleActionIfPossible)
{ {
context.getResources().getString(R.string.toggling); context.getResources().getString(R.string.toggling);
desiredState = !isEnabled; desiredState = !isEnabled;
} }
if(Build.VERSION.SDK_INT <= 20) if (Build.VERSION.SDK_INT <= 20)
{ {
for(Method m : iConnectivityManagerClass.getDeclaredMethods()) for (Method m : iConnectivityManagerClass.getDeclaredMethods())
{ {
Miscellaneous.logEvent("i", "method", m.getName(), 5); Miscellaneous.logEvent("i", "method", m.getName(), 5);
} }
@ -1116,7 +1129,7 @@ public class Actions
return true; return true;
} }
catch(Exception e) catch (Exception e)
{ {
Miscellaneous.logEvent("e", "setData", "Error changing network type: " + Log.getStackTraceString(e), 2); Miscellaneous.logEvent("e", "setData", "Error changing network type: " + Log.getStackTraceString(e), 2);
return false; return false;
@ -1128,10 +1141,10 @@ public class Actions
try try
{ {
int desiredState = 0; int desiredState = 0;
if(enable) if (enable)
desiredState = 1; desiredState = 1;
if(MobileDataStuff.setMobileNetworkFromLollipop(desiredState, autoMationServerRef)) if (MobileDataStuff.setMobileNetworkFromLollipop(desiredState, autoMationServerRef))
{ {
Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2); Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", Miscellaneous.getAnyContext().getResources().getString(R.string.dataConWithRootSuccess), 2);
return true; return true;
@ -1142,10 +1155,10 @@ public class Actions
return false; return false;
} }
} }
catch(Exception e) catch (Exception e)
{ {
String rootString; String rootString;
if(Miscellaneous.isPhoneRooted()) if (Miscellaneous.isPhoneRooted())
rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsRooted); rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsRooted);
else else
rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsNotRooted); rootString = Miscellaneous.getAnyContext().getResources().getString(R.string.phoneIsNotRooted);
@ -1182,7 +1195,7 @@ public class Actions
// mobile network for a subscription service. // mobile network for a subscription service.
command = "service call phone " + transactionCode + " i32 " + subscriptionId + " i32 " + desiredState; command = "service call phone " + transactionCode + " i32 " + subscriptionId + " i32 " + desiredState;
Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", "Running command: " + command.toString(), 5); Miscellaneous.logEvent("i", "setDataConnectionWithRoot()", "Running command: " + command.toString(), 5);
return executeCommandViaSu(new String[] { command }); return executeCommandViaSu(new String[]{command});
} }
} }
} }
@ -1193,11 +1206,11 @@ public class Actions
{ {
// Execute the command via `su` to turn off mobile network. // Execute the command via `su` to turn off mobile network.
command = "service call phone " + transactionCode + " i32 " + desiredState; command = "service call phone " + transactionCode + " i32 " + desiredState;
return executeCommandViaSu(new String[] { command }); return executeCommandViaSu(new String[]{command});
} }
} }
} }
catch(Exception e) catch (Exception e)
{ {
// Oops! Something went wrong, so we throw the exception here. // Oops! Something went wrong, so we throw the exception here.
throw e; throw e;
@ -1211,7 +1224,7 @@ public class Actions
{ {
boolean isEnabled = false; boolean isEnabled = false;
if(Build.VERSION.SDK_INT <= 20) if (Build.VERSION.SDK_INT <= 20)
{ {
try try
{ {
@ -1223,10 +1236,10 @@ public class Actions
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
Method getMobileDataEnabledMethod = null; Method getMobileDataEnabledMethod = null;
for(Method m : iConnectivityManagerClass.getDeclaredMethods()) for (Method m : iConnectivityManagerClass.getDeclaredMethods())
{ {
Miscellaneous.logEvent("i", "Methods", m.getName(), 5); Miscellaneous.logEvent("i", "Methods", m.getName(), 5);
if(m.getName().equals("getMobileDataEnabled")) if (m.getName().equals("getMobileDataEnabled"))
{ {
getMobileDataEnabledMethod = m; getMobileDataEnabledMethod = m;
break; break;
@ -1289,7 +1302,7 @@ public class Actions
suVersionInternal = Shell.SU.version(true); suVersionInternal = Shell.SU.version(true);
suResult = Shell.SU.run(commands); suResult = Shell.SU.run(commands);
if(suResult != null) if (suResult != null)
success = true; success = true;
} }
} }
@ -1303,12 +1316,24 @@ public class Actions
public static void setScreenBrightness(boolean autoBrightness, int brightnessValue) public static void setScreenBrightness(boolean autoBrightness, int brightnessValue)
{ {
if(autoBrightness) if (autoBrightness)
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
else else
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
int actualBrightnessValue = (int)((float)brightnessValue / 100.0 * 255.0); int actualBrightnessValue = (int) ((float) brightnessValue / 100.0 * 255.0);
android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, actualBrightnessValue); android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, actualBrightnessValue);
} }
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;
}
}
} }

View File

@ -36,7 +36,7 @@ public class ActivityManageActionSendTextMessage extends Activity
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.send_textmessage_editor); this.setContentView(R.layout.activity_manage_action_send_textmessage);
etSendTextMessage = (EditText)findViewById(R.id.etSendTextMessage); etSendTextMessage = (EditText)findViewById(R.id.etSendTextMessage);
etPhoneNumber = (EditText)findViewById(R.id.etPhoneNumber); etPhoneNumber = (EditText)findViewById(R.id.etPhoneNumber);

View File

@ -24,7 +24,7 @@ public class ActivityManageActionSpeakText extends Activity
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.speak_text_editor); this.setContentView(R.layout.activity_manage_action_speak_text);
etSpeakText = (EditText)findViewById(R.id.etTextToSpeak); etSpeakText = (EditText)findViewById(R.id.etTextToSpeak);
bSaveSpeakText = (Button)findViewById(R.id.bSaveTriggerUrl); bSaveSpeakText = (Button)findViewById(R.id.bSaveTriggerUrl);

View File

@ -39,7 +39,7 @@ public class ActivityManageActionTriggerUrl extends Activity
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_manage_action_url_editor); this.setContentView(R.layout.activity_manage_action_trigger_url);
etTriggerUrl = (EditText)findViewById(R.id.etTriggerUrl); etTriggerUrl = (EditText)findViewById(R.id.etTriggerUrl);
etTriggerUrlUsername = (EditText)findViewById(R.id.etTriggerUrlUsername); etTriggerUrlUsername = (EditText)findViewById(R.id.etTriggerUrlUsername);

View File

@ -1483,13 +1483,13 @@ public class ActivityManageRule extends Activity
} }
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setAirplaneMode.toString())) else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setAirplaneMode.toString()))
{ {
if(Build.VERSION.SDK_INT >= 17)
{
Toast.makeText(context, getResources().getString(R.string.airplaneModeSdk17Warning), Toast.LENGTH_LONG).show();
Miscellaneous.messageBox(getResources().getString(R.string.airplaneMode), getResources().getString(R.string.rootExplanation), ActivityManageRule.this).show();
}
newAction.setAction(Action_Enum.setAirplaneMode); newAction.setAction(Action_Enum.setAirplaneMode);
getActionParameter1Dialog(ActivityManageRule.this).show(); getActionParameter1Dialog(ActivityManageRule.this).show();
if(Build.VERSION.SDK_INT >= 17)
{
// Toast.makeText(context, getResources().getString(R.string.airplaneModeSdk17Warning), Toast.LENGTH_LONG).show();
Miscellaneous.messageBox(getResources().getString(R.string.airplaneMode), getResources().getString(R.string.rootExplanation), ActivityManageRule.this).show();
}
} }
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setDataConnection.toString())) else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.setDataConnection.toString()))
{ {

View File

@ -2,17 +2,24 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_margin="10dp" > android:layout_margin="@dimen/default_margin" >
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" > android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/urlToTriggerExplanation"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView <TextView
android:id="@+id/tvRuleTitle" android:id="@+id/tvRuleTitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/urlToTrigger" /> android:text="@string/urlToTrigger" />
<EditText <EditText

View File

@ -621,4 +621,5 @@
<string name="loadWifiList">WLAN Liste laden</string> <string name="loadWifiList">WLAN Liste laden</string>
<string name="noKnownWifis">Es gibt keine bekannten WLANs auf Ihrem Gerät.</string> <string name="noKnownWifis">Es gibt keine bekannten WLANs auf Ihrem Gerät.</string>
<string name="needLocationPermForWifiList">Die Liste von WLANs auf Ihrem Gerät könnte verwendet werden, um zu ermitteln, an welchen Orten Sie waren. Deshalb ist die Positions-Berechtigung nötig, um die Liste dieser WLANs zu laden. Wenn Sie eines aus der Liste auswählen möchten, müssen Sie diese Berechtigung gewähren. Wenn nicht, können Sie immer noch eines manuell eingeben.</string> <string name="needLocationPermForWifiList">Die Liste von WLANs auf Ihrem Gerät könnte verwendet werden, um zu ermitteln, an welchen Orten Sie waren. Deshalb ist die Positions-Berechtigung nötig, um die Liste dieser WLANs zu laden. Wenn Sie eines aus der Liste auswählen möchten, müssen Sie diese Berechtigung gewähren. Wenn nicht, können Sie immer noch eines manuell eingeben.</string>
<string name="urlToTriggerExplanation">Diese Funktion öffnet NICHT den Browser, sondern löst die HTTP Anfrage im Hintergrund aus. Sie können das z.B. benutzen, um Befehle an Ihre Heimautomatisierung zu schicken.</string>
</resources> </resources>

View File

@ -408,4 +408,6 @@ Incluya las paréntecis en su texto.\n\n[uniqueid] - el número único de su dis
<string name="any">algun</string> <string name="any">algun</string>
<string name="incoming">recibidiendo</string> <string name="incoming">recibidiendo</string>
<string name="outgoing">saliendo</string> <string name="outgoing">saliendo</string>
<string name="urlToTriggerExplanation">Esa función NO abre el browser, pero provoca el URL en el segundo plano. Per ejemplo puede usarlo a enviar ordenes a su automatización de casa.</string>
<string name="noKnownWifis">No hay wifis conociendos en su disparador.</string>
</resources> </resources>

View File

@ -70,7 +70,7 @@
<string name="end">End</string> <string name="end">End</string>
<string name="save">Save</string> <string name="save">Save</string>
<string name="urlToTrigger">URL to trigger:</string> <string name="urlToTrigger">URL to trigger:</string>
<string name="urlLegend">Variables: You can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text. [uniqueid] - Your device\'s unique id [serialnr] - Your device\'s serial number [latitude] - Your device\'s latitude [longitude] - Your device\'s longitude [phonenr] - Number of last incoming or outgoing call [d] - Day of the month, 2 digits with leading zeros [m] - Numeric representation of a month, with leading zeros [Y] - A full numeric representation of a year, 4 digits [h] - 12-hour format of an hour with leading zeros [H] - 24-hour format of an hour with leading zeros [i] - Minutes with leading zeros [s] - Seconds, with leading zeros [ms] - milliseconds [notificationTitle] - title of last notification [notificationText] - text of last notification</string> <string name="urlLegend">Variables:\nYou can use the following variables. Upon triggering they will be replaced with the corresponding value on your device. Include the brackets in your text.\n\n[uniqueid] - Your device\'s unique id\n[serialnr] - Your device\'s serial number\n[latitude] - Your device\'s latitude\n[longitude] - Your device\'s longitude\n[phonenr] - Number of last incoming or outgoing call\n[d] - Day of the month, 2 digits with leading zeros\n[m] - Numeric representation of a month, with leading zeros\n[Y] - A full numeric representation of a year, 4 digits\n[h] - 12-hour format of an hour with leading zeros\n[H] - 24-hour format of an hour with leading zeros\n[i] - Minutes with leading zeros\n[s] - Seconds, with leading zeros\n[ms] - milliseconds\n[notificationTitle] - title of last notification\n[notificationText] - text of last notification</string>
<string name="wifi">wifi</string> <string name="wifi">wifi</string>
<string name="activating">Activating</string> <string name="activating">Activating</string>
<string name="deactivating">Deactivating</string> <string name="deactivating">Deactivating</string>
@ -674,4 +674,5 @@
<string name="loadWifiList">Load wifi list</string> <string name="loadWifiList">Load wifi list</string>
<string name="needLocationPermForWifiList">The list of wifis your device has been connected to could be used to determine which places you have been to. That\'s why the location permission is required to load the list of wifis. If you want to be able to pick one from the list you need to grant that permission. If not you can still enter your wifi name manually.</string> <string name="needLocationPermForWifiList">The list of wifis your device has been connected to could be used to determine which places you have been to. That\'s why the location permission is required to load the list of wifis. If you want to be able to pick one from the list you need to grant that permission. If not you can still enter your wifi name manually.</string>
<string name="noKnownWifis">There are no known wifis on your device.</string> <string name="noKnownWifis">There are no known wifis on your device.</string>
<string name="urlToTriggerExplanation">This feature does NOT open a browser, but triggers a URL in the background. You can use this e.g. to send commands to your home automation.</string>
</resources> </resources>

View File

@ -0,0 +1,3 @@
* Activate wifi tethering doesn't require root anymore
* Italian translation updated
* Spanish translation updated