Compare commits

..
Author SHA1 Message Date
jens 72040b54ae send emails 2026-10-03 18:08:22 +02:00
jens ab2b0ce34c Removed contacts permission from Google Play version 2026-10-03 17:00:11 +02:00
jens ce32502eaa URL checker 2026-10-01 18:29:17 +02:00
jens 81812eba1b Bug in German translation 2026-09-30 18:22:12 +02:00
jens e0853082b7 Minor fixes 2026-09-20 17:23:01 +02:00
jens 4673bc2289 Minor fixes 2026-08-26 16:38:38 +02:00
jens 3f28e7b2bc Fixed http request crash 2026-08-26 13:33:55 +02:00
23 changed files with 588 additions and 418 deletions
+9 -7
View File
@@ -3,16 +3,16 @@ plugins {
}
android {
compileSdkVersion 36
compileSdkVersion 37
defaultConfig {
applicationId "com.jens.automation2"
minSdkVersion 19
compileSdkVersion 36
compileSdkVersion 37
buildToolsVersion '36.0.0'
useLibrary 'org.apache.http.legacy'
versionCode 149
versionName "1.8.8"
versionCode 150
versionName "1.8.9"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -36,7 +36,7 @@ android {
{
dimension "version"
versionNameSuffix "-googlePlay"
targetSdkVersion 36
targetSdkVersion 37
}
/*
@@ -61,12 +61,12 @@ android {
lint {
abortOnError false
checkReleaseBuilds false
}
dependencies }
namespace 'com.jens.automation2'
buildToolsVersion '36.0.0'
}
dependencies {
{
implementation 'org.jetbrains:annotations:26.1.0'
googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:20.0.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:20.0.0'
@@ -77,6 +77,8 @@ dependencies {
implementation 'com.linkedin.dexmaker:dexmaker:2.28.6'
implementation 'org.apache.commons:commons-lang3:3.20.0'
implementation 'org.simplejavamail:simple-java-mail:9.3.5'
//implementation "androidx.security:security-crypto:1.0.0"
//implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation 'androidx.appcompat:appcompat:1.4.2'
+3 -1
View File
@@ -60,7 +60,9 @@
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--
Removed due to latest threat mail from Google:
<uses-permission android:name="android.permission.READ_CONTACTS"/>-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
@@ -403,7 +403,11 @@ public class ActivityDetectionReceiver extends IntentService implements Automati
private PendingIntent getActivityDetectionPendingIntent()
{
Intent intent = new Intent(AutomationService.getInstance(), ActivityDetectionReceiver.class);
PendingIntent returnValue = PendingIntent.getService(AutomationService.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent returnValue;
if(Miscellaneous.getTargetSDK(AutomationService.getInstance()) >= 31)
returnValue = PendingIntent.getService(AutomationService.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
else
returnValue = PendingIntent.getService(AutomationService.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return returnValue;
}
}
@@ -799,4 +799,16 @@ public class Action
myAction.useDownloadedWebpage(result);
}
}
public Action getClone()
{
Action clone = new Action();
clone.setAction(this.getAction());
clone.setParentRule(this.getParentRule());
clone.setParameter1(this.getParameter1());
clone.setParameter2(this.getParameter2());
return clone;
}
}
@@ -2675,4 +2675,32 @@ public class Actions
android.provider.Settings.Secure.putString(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE, String.valueOf(desiredState));
}
public static sendEmail()
{
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", "10000");
props.put("mail.smtp.timeout", "10000");
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromAddress));
message.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse(recipientAddress)
);
message.setSubject(subject);
message.setText(body);
Transport.send(message);
}
}
@@ -6,6 +6,9 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
@@ -27,9 +30,13 @@ import androidx.annotation.NonNull;
import com.jens.automation2.Action.Action_Enum;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Text;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Pattern;
public class ActivityManageActionTriggerUrl extends Activity
{
@@ -39,7 +46,7 @@ public class ActivityManageActionTriggerUrl extends Activity
CheckBox chkTriggerUrlUseAuthentication;
RadioButton rbTriggerUrlMethodGet, rbTriggerUrlMethodPost;
TableLayout tlTriggerUrlAuthentication;
TextView tvHttpParameterExplanation;
TextView tvHttpParameterExplanation, tvUrlValidator;
ArrayAdapter<String> httpParametersAdapter;
private ArrayList<String> httpParamsList = new ArrayList<>();
@@ -70,6 +77,7 @@ public class ActivityManageActionTriggerUrl extends Activity
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
bAddHttpParam = (Button)findViewById(R.id.bAddHttpParam);
tvHttpParameterExplanation = (TextView)findViewById(R.id.tvHttpParameterExplanation);
tvUrlValidator = (TextView)findViewById(R.id.tvUrlValidator);
etParameterName.setEnabled(false);
etParameterValue.setEnabled(false);
@@ -173,6 +181,33 @@ public class ActivityManageActionTriggerUrl extends Activity
});
updateListView();
etTriggerUrl.addTextChangedListener(new TextWatcher()
{
@Override
public void afterTextChanged(Editable editable)
{
if(etTriggerUrl.getText() != null && etTriggerUrl.getText().length() > 0)
{
if(Miscellaneous.isValidUrl(etTriggerUrl.getText().toString()))
tvUrlValidator.setText("");
else
tvUrlValidator.setText(getResources().getString(R.string.enter_valid_url));
}
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
});
if(getIntent().hasExtra(ActivityManageRule.intentNameActionParameter2))
{
// username,password,URL,etc.
@@ -670,6 +670,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.subsystemstate));
else if(types[i].toString().equals(Trigger_Enum.checkVariable.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
else if(types[i].toString().equals(Trigger_Enum.proximity.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.proximity));
else if(types[i].toString().equals(Trigger_Enum.calendarEvent.toString()))
{
if(ActivityPermissions.isPermissionDeclaredInManifest(ActivityManageRule.this, Manifest.permission.READ_CALENDAR))
@@ -753,7 +755,17 @@ public class ActivityManageRule extends Activity
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
else if(triggerType == Trigger_Enum.usb_host_connection)
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
else if(triggerType == Trigger_Enum.speed || triggerType == Trigger_Enum.noiseLevel || triggerType == Trigger_Enum.batteryLevel)
else if(triggerType == Trigger_Enum.speed)
{
if(Miscellaneous.googleToBlameForLocation(false))
{
ActivityMainScreen.openGoogleBlamingWindow();
return;
}
else
booleanChoices = new String[]{getResources().getString(R.string.exceeds), getResources().getString(R.string.dropsBelow)};
}
else if(triggerType == Trigger_Enum.noiseLevel || triggerType == Trigger_Enum.batteryLevel)
booleanChoices = new String[]{getResources().getString(R.string.exceeds), getResources().getString(R.string.dropsBelow)};
else if(triggerType == Trigger_Enum.wifiConnection)
{
@@ -2613,17 +2625,24 @@ public class ActivityManageRule extends Activity
return alertDialog;
}
private AlertDialog getTriggerDeleteDialog(Context myContext, final Trigger triggerToBeDeleted)
private AlertDialog getTriggerDeleteDialog(Context myContext, final Trigger selectedTrigger)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(getResources().getString(R.string.whatToDoWithTrigger));
alertDialogBuilder.setItems(new String[]{getResources().getString(R.string.delete)}, new DialogInterface.OnClickListener()
alertDialogBuilder.setItems(new String[]{getResources().getString(R.string.delete), getResources().getString(R.string.clone)}, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// Only 1 choice at the moment, no need to check
ruleToEdit.getTriggerSet().remove(triggerToBeDeleted);
switch(which)
{
case 0:
ruleToEdit.getTriggerSet().remove(selectedTrigger);
break;
case 1:
ruleToEdit.getTriggerSet().add(selectedTrigger.getClone());
break;
}
refreshTriggerList();
}
});
@@ -2635,7 +2654,7 @@ public class ActivityManageRule extends Activity
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(getResources().getString(R.string.whatToDoWithAction));
alertDialogBuilder.setItems(new String[] { getResources().getString(R.string.delete), getResources().getString(R.string.moveUp), getResources().getString(R.string.moveDown)}, new DialogInterface.OnClickListener()
alertDialogBuilder.setItems(new String[] { getResources().getString(R.string.delete), getResources().getString(R.string.moveUp), getResources().getString(R.string.moveDown), getResources().getString(R.string.clone)}, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
@@ -2680,6 +2699,11 @@ public class ActivityManageRule extends Activity
Toast.makeText(ActivityManageRule.this, getResources().getString(R.string.cantMoveDown), Toast.LENGTH_LONG).show();
}
break;
case 3:
// create clone
ruleToEdit.getActionSet().add(actionToBeDeleted.getClone());
refreshActionList();
break;
}
}
});
@@ -102,6 +102,12 @@ public class ActivityManageTriggerPhoneCall extends Activity
@Override
public void onClick(View view)
{
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
{
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.featureNotInGooglePlayVersion), ActivityManageTriggerPhoneCall.this).show();
return;
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !ActivityPermissions.havePermission("android.permission.READ_CONTACTS", ActivityManageTriggerPhoneCall.this))
{
requestPermissions("android.permission.READ_CONTACTS");
@@ -469,7 +469,7 @@ public class AutomationService extends Service implements OnInitListener
if(displayNotification)
{
Intent intent = new Intent(AutomationService.this, ActivityPermissions.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, FLAG_IMMUTABLE);
Miscellaneous.logEvent("w", "Features disabled", "Features disabled because of rule " + rule, 5);
@@ -105,6 +105,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@@ -133,6 +135,9 @@ public class Miscellaneous extends Service
protected final static String httpMainData = "httpMainData";
protected final static String doNoEncodingString = "NoEncoding";
protected final static String httpEncoding = "UTF-8";
protected final static String URL_REGEX = "^(https?):\\/\\/([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)(:[0-9]{1,5})?([\\/\\?#].*)?$";
// protected final static String URL_REGEX = "^(https?|ftp):\\/\\/([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)(:[0-9]{1,5})?([\\/\\?#].*)?$";
protected final static Pattern URL_PATTERN = Pattern.compile(URL_REGEX, Pattern.CASE_INSENSITIVE);
public static Context startupContext;
public static final String lineSeparator = System.getProperty("line.separator");
@@ -201,7 +206,7 @@ public class Miscellaneous extends Service
else if (method.equals(ActivityManageActionTriggerUrl.methodPost))
connection.setRequestMethod("POST");
if(httpParams.size() > 0)
if (httpParams != null && httpParams.size() > 0)
{
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
@@ -409,6 +414,7 @@ public class Miscellaneous extends Service
}
protected static boolean logCleanerRunning = false;
protected static void rotateLogFile(File logFile)
{
logCleanerRunning = true;
@@ -522,7 +528,8 @@ public class Miscellaneous extends Service
}
// }
}
} catch (Exception e)
}
catch (Exception e)
{
Log.w("getWritableFolder", folder + " not writable.");
}
@@ -534,6 +541,7 @@ public class Miscellaneous extends Service
}
protected final static String logFileName = "Automation_logfile.txt";
protected static File getLogFile()
{
File logFile = null;
@@ -553,6 +561,7 @@ public class Miscellaneous extends Service
return logFile;
}
private static void writeToLogFile(String type, String header, String description)
{
try
@@ -1061,7 +1070,8 @@ public class Miscellaneous extends Service
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
for (NetworkInfo ni : netInfo)
{
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.isConnected())
haveConnectedWifi = true;
@@ -1295,7 +1305,8 @@ public class Miscellaneous extends Service
Thread.sleep(delay);
}
catch (Exception e)
{}
{
}
createDismissibleNotification(title, textToDisplay, notificationId, true, notificationChannelId, pendingIntent);
@@ -1359,6 +1370,7 @@ public class Miscellaneous extends Service
return null;
}
@RequiresApi(api = Build.VERSION_CODES.O)
static NotificationChannel getNotificationChannel(String channelId)
{
@@ -2270,6 +2282,7 @@ public class Miscellaneous extends Service
/**
* Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
*
* @param context Context reference to get the TelephonyManager instance from
* @return country code or null
*/
@@ -2297,7 +2310,8 @@ public class Miscellaneous extends Service
return "unknown";
}
catch (Exception e)
{ }
{
}
return null;
}
@@ -2356,7 +2370,18 @@ public class Miscellaneous extends Service
public static void setDisplayLanguage(Context context)
{
if(!Settings.displayLanguage.equals(Settings.default_displayLanguage))
String targetLanguage = null;
if (Settings.displayLanguage == null)
{
targetLanguage = Settings.default_displayLanguage;
}
else if (!Settings.displayLanguage.equals(Settings.default_displayLanguage))
{
targetLanguage = Settings.default_displayLanguage;
}
if (targetLanguage != null)
{
Locale myLocale;
@@ -2408,4 +2433,13 @@ public class Miscellaneous extends Service
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
public static boolean isValidUrl(String input)
{
if (input == null || input.length() == 0)
return false;
Matcher matcher = URL_PATTERN.matcher(input);
return matcher.matches(); // Returns true if the entire string matches
}
}
@@ -2092,4 +2092,16 @@ public class Trigger
{
this.parentRule = parentRule;
}
public Trigger getClone()
{
Trigger clone = new Trigger();
clone.setTriggerType(this.getTriggerType());
clone.setParentRule(this.getParentRule());
clone.setTriggerParameter(this.getTriggerParameter());
clone.setTriggerParameter2(this.getTriggerParameter2());
return clone;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -35,6 +35,12 @@
</EditText>
<TextView
android:id="@+id/tvUrlValidator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/red" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+2 -2
View File
@@ -697,7 +697,7 @@
<string name="screenIs">Bildschirm ist %1$s</string>
<string name="sendEmailToDev">Email an Entwickler schicken</string>
<string name="controlCenter">Steuerungszentrale</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">Forum</a> stellen.</string>
<string name="contactNotice">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.\nIch kann absolut nachvollziehen, wenn Sie Ihre Privatspäre schützen möchten, aber ich möchte Sie bitten, sich zumindest mit Ihrem Vornamen zu melden, um einen normalen freundlichen Austausch zu vereinfachen.\n\nAlternativ können Sie Ihre Frage im <a href="https://forum.server47.de">Forum</a> stellen.</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Aufgrund Google\'s unendlicher Weisheit, ist die letzte Android Version, mit der diese Funktion noch funktioniert, die Version %1$s. Sie können es hier einrichten, aber vermutlich wird es keine Auswirkung haben.</string>
<string name="musicPlaying">Musik läuft</string>
<string name="selectParameters">Wählen Sie die Parameter</string>
@@ -887,5 +887,5 @@
<string name="enterAvalue">Geben Sie einen Wert ein.</string>
<string name="setSystemSettingCapital">Systemeinstellung setzen</string>
<string name="examplesWriteSecureSettings">Ich führe keine Liste möglicher Einstellungen. Bitte finden Sie diese Einstellungen selbst. Siehe <a href="https://developer.android.com/reference/android/provider/Settings.Secure">hier</a> für einige (unvollständige) Beispiele.</string>
<string name="httpParametersExplanation">Beginnt ein Parametername mit %1$s, während die Methode POST ist, wird er nicht wie die anderen Parameter (mit Schlüssel=Wert) übertragen, sondern als Hauptdaten übertragen. Wenn der Parameter mit 2 % endet, wird keine Codierung durchgeführt.</string>
<string name="httpParametersExplanation">Beginnt ein Parametername mit %1$s, während die Methode POST ist, wird er nicht wie die anderen Parameter (mit Schlüssel=Wert) übertragen, sondern als Hauptdaten übertragen. Wenn der Parameter mit %2$s endet, wird keine Codierung durchgeführt.</string>
</resources>
+1 -1
View File
@@ -696,7 +696,7 @@
<string name="screenIs">pantalla esta %1$s</string>
<string name="sendEmailToDev">Enviar email al desrollador</string>
<string name="featureCeasedToWorkLastWorkingAndroidVersion">Debido a la infinita sabiduría de Google, la última versión de Android en la que se sabe que funciona esta función es %1$s. Puede configurarlo, pero probablemente no tendrá ningún efecto.</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">foro</a>.</string>
<string name="contactNotice">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.\nEntiendo perfectamente el impulso de proteger tu privacidad, pero te pido que reveles al menos tu nombre de pila para permitir una conversación amistosa.\n\nAlternativamente, tiene la opción de hacer sus preguntas en el <a href="https://forum.server47.de">foro</a>.</string>
<string name="actionMediaControlNotice">Ten en cuenta que esta acción puede no funcionar con TODOS los jugadores. E incluso si lo hace, no todos los botones funcionan necesariamente.</string>
<string name="musicPlaying">Musica esta reproduciendo</string>
<string name="selectParameters">Elije parametros</string>
+1 -1
View File
@@ -678,7 +678,7 @@
<string name="comparisonCaseInsensitive">La coparaisonn est sensible à la casse du texte</string>
<string name="profileWarning">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.</string>
<string name="ifString">si</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">forum</a>.</string>
<string name="contactNotice">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.\nJe comprends parfaitement l\'envie de protéger votre vie privée, mais je vous demande de révéler au moins votre prénom pour permettre une conversation amicale.\n\nSinon, vous avez la possibilité de poser vos questions dans le <a href="https://forum.server47.de">forum</a>.</string>
<string name="controlCenter">Centre de contrôle</string>
<string name="sendEmailToDev">Envoyer un email au développeur</string>
<string name="screenIs">l’écran est %1$s</string>
+1 -1
View File
@@ -698,7 +698,7 @@
<string name="screenIs">lo schermo è %1$s</string>
<string name="sendEmailToDev">Invia email allo sviluppatore</string>
<string name="controlCenter">Centro di controllo</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">forum</a>.</string>
<string name="contactNotice">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.\nCapisco perfettamente l\'impulso a proteggere la tua privacy, ma ti chiedo di rivelare almeno il tuo nome di battesimo per permettere una conversazione amichevole.\n\nIn alternativa hai la possibilità di porre le tue domande nel <a href="https://forum.server47.de">forum</a>.</string>
<string name="musicPlaying">La musica è in riproduzione</string>
<string name="musicIsPlaying">la musica è in riproduzione</string>
<string name="musicIsNotPlaying">la musica non viene riprodotta</string>
+1 -1
View File
@@ -676,7 +676,7 @@
<string name="comparisonCaseInsensitive">Vergelijkingen worden gedaan case-INsensitief</string>
<string name="profileWarning">De instellingen die je hier maakt kunnen ervoor zorgen dat je bepaalde dingen niet meer van je telefoon merkt. Ze kunnen zelfs je wekker dempen. Dus wat je ook doet - het wordt aanbevolen om het te testen - ook na Android upgrades.</string>
<string name="ifString">als</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">forum</a>.</string>
<string name="contactNotice">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.\nIk begrijp absoluut de drang om je privacy te beschermen, maar ik vraag je om ten minste je voornaam te onthullen om een vriendelijk gesprek mogelijk te maken.\n\nJe hebt ook de mogelijkheid om je vragen te stellen in het <a href="https://forum.server47.de">forum</a>.</string>
<string name="controlCenter">Controlecentrum</string>
<string name="sendEmailToDev">Stuur een e-mail naar de ontwikkelaar</string>
<string name="screenIs">scherm is %1$s</string>
+1 -1
View File
@@ -768,7 +768,7 @@
<string name="comparisonCaseInsensitive">Porównania nie uwzględniają wielkości liter</string>
<string name="profileWarning">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.</string>
<string name="ifString">jeśli</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">forum</a>.</string>
<string name="contactNotice">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.\Całkowicie rozumiem chęć ochrony prywatności, ale proszę, byś przynajmniej ujawnił swoje imię, żeby móc przeprowadzić przyjazną rozmowę.\n\nAlternatywnie masz możliwość zadawania pytań na <a href="https://forum.server47.de">forum</a>.</string>
<string name="controlCenter">Centrum kontroli</string>
<string name="sendEmailToDev">Wyślij wiadomość e-mail do programisty</string>
<string name="screenIs">ekran to %1$s</string>
+1 -1
View File
@@ -735,7 +735,7 @@
<string name="comparisonCaseInsensitive">Сравнения проводятся без учета регистра</string>
<string name="profileWarning">Настройки, которые вы можете изменить здесь, могут привести к тому, что вы больше не заметите определенных вещей с вашего телефона. Они могут даже отключить будильник. Так что что бы вы ни делали - рекомендуется это проверять.</string>
<string name="ifString">если</string>
<string name="contactNotice">Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.\nМногие вопросы не могут быть решены сразу, но требуют некоторых технических исследований. Поэтому, пожалуйста, наберитесь терпения. \n\nВ качестве альтернативы у вас есть возможность задать свои вопросы на <a href="https://forum.server47.de">форуме</a>.</string>
<string name="contactNotice">Электронная почта - мой предпочтительный способ связи, для сообщений об ошибках, вопросов или предложений. Перейдите в центр управления, чтобы узнать больше.\nМногие вопросы не могут быть решены сразу, но требуют некоторых технических исследований. Поэтому, пожалуйста, наберитесь терпения.\nЯ полностью понимаю желание защитить вашу приватность, но прошу вас хотя бы раскрыть своё имя для дружеской беседы.\n\nВ качестве альтернативы у вас есть возможность задать свои вопросы на <a href="https://forum.server47.de">форуме</a>.</string>
<string name="controlCenter">Центр управления</string>
<string name="sendEmailToDev">Отправить электронное письмо разработчику</string>
<string name="screenIs">экран %1$s</string>
+1 -1
View File
@@ -670,7 +670,7 @@
<string name="comparisonCaseInsensitive">比较不区分大小写</string>
<string name="profileWarning">此处的设置可能会导致您无法再注意到手机中的某些内容,甚至可以让您的起床闹钟静音。所以无论怎样设置——强烈建议测试,在 Android 更新之后也要再测试。</string>
<string name="ifString">如果</string>
<string name="contactNotice">电子邮件是向我报告错误、提出问题或建议的首选联系方式。前往控制中心了解更多信息。\n许多问题无法立即解答,需要进行一些技术研究。所以请耐心等待。 \n\n或者,您可以选择在 <a href="https://forum.server47.de">论坛</a>中提问 。</string>
<string name="contactNotice">电子邮件是向我报告错误、提出问题或建议的首选联系方式。前往控制中心了解更多信息。\n许多问题无法立即解答,需要进行一些技术研究。所以请耐心等待。\n我完全理解你想保护隐私的冲动,但我请求你至少透露你的名字,以便友好交流。\n\n或者,您可以选择在 <a href="https://forum.server47.de">论坛</a>中提问 。</string>
<string name="controlCenter">控制中心</string>
<string name="sendEmailToDev">向开发者发送电子邮件</string>
<string name="screenIs">屏幕 %1$s</string>
+3 -2
View File
@@ -698,7 +698,7 @@
<string name="bottom">Bottom</string>
<string name="tabsPlacement">Position of tab bar</string>
<string name="tabsPlacementSummary">Choose where the tabs bar should be placed.</string>
<string name="wifiApi30">Because Google screwed up yet another part of Android, starting with API 30 only the currently visible wifis can be displayed, not all the ones your device has connected to anymore.</string>
<string name="wifiApi30">Because Google screwed up yet another part of Android, starting with API 30 only the currently visible Wi-Fi can be displayed, not all the ones your device has connected to anymore.</string>
<string name="silentTriggersDnd">REMARK: The silent mode often triggers Do-Not-Disturb on newer devices. If that happens on your device, I recommend using the normal mode instead and lowering all volumes to zero.</string>
<string name="tones">Tones</string>
<string name="miscellaneous">Miscellaneous</string>
@@ -770,7 +770,7 @@
<string name="comparisonCaseInsensitive">Comparisons are done case-INsensitive</string>
<string name="profileWarning">The settings you can adjust here, can cause that you don\'t notice certain things from your phone anymore. They may even silence your wakeup alarm. So whatever you do - it is highly recommended that you test it - also after Android updates.</string>
<string name="ifString">if</string>
<string name="contactNotice">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 <a href="https://forum.server47.de">forum</a>.</string>
<string name="contactNotice">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.\nI absolutely understand the urge to protect your privacy, but I think you can at least reveal your first name to allow for a friendly conversation.\n\nAlternatively you have the option of asking your questions in the <a href="https://forum.server47.de">forum</a>.</string>
<string name="controlCenter">Control center</string>
<string name="sendEmailToDev">Send email to developer</string>
<string name="screenIs">screen is %1$s</string>
@@ -979,4 +979,5 @@
<string name="examplesWriteSecureSettings">I do not keep a list of possible settings. Please find those settings on your own. See <a href="https://developer.android.com/reference/android/provider/Settings.Secure">here</a> for some (incomplete) examples.</string>
<string name="httpParametersExplanation">If any parameter name starts with %1$s while method is POST, it will not be transmitted like the other parameters (with key=value), but transferred as main data. If the parameter ends with %2$s, no encoding will be performed.</string>
<string name="target">Target</string>
<string name="enter_valid_url">Enter a valid URL.</string>
</resources>
@@ -0,0 +1,4 @@
* Added: Triggers and actions can now be cloned
* Added: URL checker for triggerUrl action
* Fixed: Crash when starting to add/edit a triggerURL action while the app or the system are set to the German language
* Fixed: Crash when starting service in Google Play version