Compare commits
19 Commits
17b3b8fafc
...
v1.8.1
Author | SHA1 | Date | |
---|---|---|---|
9f36411511 | |||
eb893a7f21 | |||
8788a89e48 | |||
bb10620883 | |||
3e29054f82 | |||
9d5f0a3cef | |||
695b1f2481 | |||
d7357b0b0f | |||
e272338cc6 | |||
3dd84220a3 | |||
4bc2781ee7 | |||
62bfbbb064 | |||
31d167a93f | |||
500610fb98 | |||
5ca7295c30 | |||
e2027a457a | |||
6c31b67b14 | |||
04fe674cf6 | |||
6e73c74b60 |
@ -11,8 +11,8 @@ android {
|
|||||||
compileSdkVersion 33
|
compileSdkVersion 33
|
||||||
buildToolsVersion '29.0.2'
|
buildToolsVersion '29.0.2'
|
||||||
useLibrary 'org.apache.http.legacy'
|
useLibrary 'org.apache.http.legacy'
|
||||||
versionCode 138
|
versionCode 142
|
||||||
versionName "1.8"
|
versionName "1.8.1"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,7 @@
|
|||||||
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
||||||
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
||||||
<activity android:name=".ActivityManageActionLocationService" />
|
<activity android:name=".ActivityManageActionLocationService" />
|
||||||
|
<activity android:name=".ActivityManageTriggerCharging" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActivityMainTabLayout"
|
android:name=".ActivityMainTabLayout"
|
||||||
|
@ -865,4 +865,17 @@ public class Rule implements Comparable<Rule>
|
|||||||
|
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getAmountOfActivatedRules()
|
||||||
|
{
|
||||||
|
int amount = 0;
|
||||||
|
|
||||||
|
for(Rule r : Rule.getRuleCollection())
|
||||||
|
{
|
||||||
|
if(r.isRuleActive())
|
||||||
|
amount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
}
|
}
|
@ -189,6 +189,7 @@
|
|||||||
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
||||||
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
||||||
<activity android:name=".ActivityManageActionLocationService" />
|
<activity android:name=".ActivityManageActionLocationService" />
|
||||||
|
<activity android:name=".ActivityManageTriggerCharging" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActivityMainTabLayout"
|
android:name=".ActivityMainTabLayout"
|
||||||
|
@ -838,4 +838,17 @@ public class Rule implements Comparable<Rule>
|
|||||||
|
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getAmountOfActivatedRules()
|
||||||
|
{
|
||||||
|
int amount = 0;
|
||||||
|
|
||||||
|
for(Rule r : Rule.getRuleCollection())
|
||||||
|
{
|
||||||
|
if(r.isRuleActive())
|
||||||
|
amount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,6 @@
|
|||||||
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
|
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_SECURE_SETTINGS"
|
android:name="android.permission.WRITE_SECURE_SETTINGS"
|
||||||
tools:ignore="ProtectedPermissions" />
|
tools:ignore="ProtectedPermissions" />
|
||||||
@ -175,6 +174,7 @@
|
|||||||
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
<activity android:name=".ActivityManageTriggerCheckVariable" />
|
||||||
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
<activity android:name=".ActivityManageActionCopyToClipboard" />
|
||||||
<activity android:name=".ActivityManageActionLocationService" />
|
<activity android:name=".ActivityManageActionLocationService" />
|
||||||
|
<activity android:name=".ActivityManageTriggerCharging" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActivityMainTabLayout"
|
android:name=".ActivityMainTabLayout"
|
||||||
@ -257,18 +257,6 @@
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<service android:name=".MyAccessibilityService"
|
|
||||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.accessibilityservice"
|
|
||||||
android:resource="@xml/config_accessibility_service" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -865,4 +865,17 @@ public class Rule implements Comparable<Rule>
|
|||||||
|
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getAmountOfActivatedRules()
|
||||||
|
{
|
||||||
|
int amount = 0;
|
||||||
|
|
||||||
|
for(Rule r : Rule.getRuleCollection())
|
||||||
|
{
|
||||||
|
if(r.isRuleActive())
|
||||||
|
amount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1107,7 +1107,13 @@ public class Actions
|
|||||||
externalApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
externalApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
// Pack intents
|
// Pack intents
|
||||||
externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 3);
|
if(params.length >= 4)
|
||||||
|
{
|
||||||
|
if(Miscellaneous.isNumeric(params[3]))
|
||||||
|
externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 4);
|
||||||
|
else
|
||||||
|
externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 3);
|
||||||
|
}
|
||||||
|
|
||||||
if (params[2].equals(ActivityManageActionStartActivity.startByActivityString))
|
if (params[2].equals(ActivityManageActionStartActivity.startByActivityString))
|
||||||
automationServerRef.startActivity(externalApplicationIntent);
|
automationServerRef.startActivity(externalApplicationIntent);
|
||||||
@ -2353,7 +2359,8 @@ public class Actions
|
|||||||
{
|
{
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||||
{
|
{
|
||||||
MyAccessibilityService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
|
if(!BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
|
||||||
|
MyAccessibilityService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,15 +526,23 @@ public class ActivityMainScreen extends ActivityGeneric
|
|||||||
{
|
{
|
||||||
if (Rule.getRuleCollection().size() > 0)
|
if (Rule.getRuleCollection().size() > 0)
|
||||||
{
|
{
|
||||||
|
if(Rule.getAmountOfActivatedRules() == 0)
|
||||||
|
{
|
||||||
|
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStartNoActivatedRules), Toast.LENGTH_LONG).show();
|
||||||
|
activityMainScreenInstance.toggleService.setChecked(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!AutomationService.isMyServiceRunning(context))
|
if (!AutomationService.isMyServiceRunning(context))
|
||||||
{
|
{
|
||||||
// if(myServiceIntent == null) //do we need that line?????
|
|
||||||
myServiceIntent = new Intent(context, AutomationService.class);
|
myServiceIntent = new Intent(context, AutomationService.class);
|
||||||
myServiceIntent.putExtra("startAtBoot", startAtBoot);
|
myServiceIntent.putExtra("startAtBoot", startAtBoot);
|
||||||
context.startService(myServiceIntent);
|
context.startService(myServiceIntent);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
Miscellaneous.logEvent("w", "Service", context.getResources().getString(R.string.logServiceAlreadyRunning), 3);
|
Miscellaneous.logEvent("w", "Service", context.getResources().getString(R.string.logServiceAlreadyRunning), 3);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
|
||||||
activityMainScreenInstance.toggleService.setChecked(false);
|
activityMainScreenInstance.toggleService.setChecked(false);
|
||||||
|
@ -145,6 +145,8 @@ public class ActivityManageRule extends Activity
|
|||||||
final static int requestCodeActionSetLocationServiceEdit = 832;
|
final static int requestCodeActionSetLocationServiceEdit = 832;
|
||||||
final static int requestCodeTriggerCalendarEventAdd = 833;
|
final static int requestCodeTriggerCalendarEventAdd = 833;
|
||||||
final static int requestCodeTriggerCalendarEventEdit = 834;
|
final static int requestCodeTriggerCalendarEventEdit = 834;
|
||||||
|
final static int requestCodeTriggerChargingAdd = 835;
|
||||||
|
final static int requestCodeTriggerChargingEdit = 836;
|
||||||
|
|
||||||
public static ActivityManageRule getInstance()
|
public static ActivityManageRule getInstance()
|
||||||
{
|
{
|
||||||
@ -355,6 +357,12 @@ public class ActivityManageRule extends Activity
|
|||||||
calendarStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
|
calendarStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
|
||||||
startActivityForResult(calendarStateEditor, requestCodeTriggerCalendarEventEdit);
|
startActivityForResult(calendarStateEditor, requestCodeTriggerCalendarEventEdit);
|
||||||
break;
|
break;
|
||||||
|
case charging:
|
||||||
|
Intent chargingStateEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerCharging.class);
|
||||||
|
chargingStateEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
|
||||||
|
chargingStateEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
|
||||||
|
startActivityForResult(chargingStateEditor, requestCodeTriggerChargingEdit);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -396,9 +404,6 @@ public class ActivityManageRule extends Activity
|
|||||||
break;
|
break;
|
||||||
case triggerUrl:
|
case triggerUrl:
|
||||||
Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class);
|
Intent activityEditTriggerUrlIntent = new Intent(ActivityManageRule.this, ActivityManageActionTriggerUrl.class);
|
||||||
// ActivityManageActionTriggerUrl.resultingAction = a;
|
|
||||||
// ActivityManageActionTriggerUrl.resultingAction.setParentRule(ruleToEdit);
|
|
||||||
// activityEditTriggerUrlIntent.putExtra("edit", true);
|
|
||||||
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter1, a.getParameter1());
|
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter1, a.getParameter1());
|
||||||
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter2, a.getParameter2());
|
activityEditTriggerUrlIntent.putExtra(intentNameActionParameter2, a.getParameter2());
|
||||||
startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit);
|
startActivityForResult(activityEditTriggerUrlIntent, requestCodeActionTriggerUrlEdit);
|
||||||
@ -617,7 +622,7 @@ public class ActivityManageRule extends Activity
|
|||||||
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
|
items.add(new Item(typesLong[i].toString(), R.drawable.megaphone));
|
||||||
else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString()))
|
else if(types[i].toString().equals(Trigger_Enum.phoneCall.toString()))
|
||||||
{
|
{
|
||||||
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, "android.permission.SEND_SMS"))
|
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.SEND_SMS))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
|
items.add(new Item(typesLong[i].toString(), R.drawable.phone));
|
||||||
}
|
}
|
||||||
else if(types[i].toString().equals(Trigger_Enum.nfcTag.toString()))
|
else if(types[i].toString().equals(Trigger_Enum.nfcTag.toString()))
|
||||||
@ -649,7 +654,10 @@ public class ActivityManageRule extends Activity
|
|||||||
else if(types[i].toString().equals(Trigger_Enum.checkVariable.toString()))
|
else if(types[i].toString().equals(Trigger_Enum.checkVariable.toString()))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
|
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
|
||||||
else if(types[i].toString().equals(Trigger_Enum.calendarEvent.toString()))
|
else if(types[i].toString().equals(Trigger_Enum.calendarEvent.toString()))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.calendar));
|
{
|
||||||
|
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.READ_CALENDAR))
|
||||||
|
items.add(new Item(typesLong[i].toString(), R.drawable.calendar));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
|
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
|
||||||
}
|
}
|
||||||
@ -710,7 +718,14 @@ public class ActivityManageRule extends Activity
|
|||||||
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeAdd);
|
startActivityForResult(timeFrameEditor, requestCodeTriggerTimeframeAdd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(triggerType == Trigger_Enum.charging || triggerType == Trigger_Enum.musicPlaying)
|
else if(triggerType == Trigger_Enum.charging)
|
||||||
|
{
|
||||||
|
newTrigger.setTriggerType(Trigger_Enum.charging);
|
||||||
|
Intent triggerChargingIntent = new Intent(myContext, ActivityManageTriggerCharging.class);
|
||||||
|
startActivityForResult(triggerChargingIntent, requestCodeTriggerChargingAdd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(triggerType == Trigger_Enum.musicPlaying)
|
||||||
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
|
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
|
||||||
else if(triggerType == Trigger_Enum.usb_host_connection)
|
else if(triggerType == Trigger_Enum.usb_host_connection)
|
||||||
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
|
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
|
||||||
@ -1460,6 +1475,30 @@ public class ActivityManageRule extends Activity
|
|||||||
this.refreshTriggerList();
|
this.refreshTriggerList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(requestCode == requestCodeTriggerChargingAdd)
|
||||||
|
{
|
||||||
|
if(resultCode == RESULT_OK)
|
||||||
|
{
|
||||||
|
newTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
|
||||||
|
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
|
||||||
|
newTrigger.setParentRule(ruleToEdit);
|
||||||
|
ruleToEdit.getTriggerSet().add(newTrigger);
|
||||||
|
this.refreshTriggerList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(requestCode == requestCodeTriggerChargingEdit)
|
||||||
|
{
|
||||||
|
if(resultCode == RESULT_OK)
|
||||||
|
{
|
||||||
|
Trigger responseTimeFrame = new Trigger();
|
||||||
|
responseTimeFrame.setTriggerType(Trigger_Enum.charging);
|
||||||
|
responseTimeFrame.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
|
||||||
|
responseTimeFrame.setTriggerParameter2(data.getStringExtra(intentNameTriggerParameter2));
|
||||||
|
responseTimeFrame.setParentRule(ruleToEdit);
|
||||||
|
ruleToEdit.getTriggerSet().set(editIndex, responseTimeFrame);
|
||||||
|
this.refreshTriggerList();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(requestCode == requestCodeActionStartActivityAdd)
|
else if(requestCode == requestCodeActionStartActivityAdd)
|
||||||
{
|
{
|
||||||
// manage start of other activity
|
// manage start of other activity
|
||||||
@ -2214,12 +2253,15 @@ public class ActivityManageRule extends Activity
|
|||||||
}
|
}
|
||||||
else if(types[i].toString().equals(Action_Enum.copyToClipboard.toString()))
|
else if(types[i].toString().equals(Action_Enum.copyToClipboard.toString()))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.clipboard));
|
items.add(new Item(typesLong[i].toString(), R.drawable.clipboard));
|
||||||
else if(types[i].toString().equals(Action_Enum.takeScreenshot.toString()))
|
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.copier));
|
|
||||||
else if(types[i].toString().equals(Action_Enum.setVariable.toString()))
|
else if(types[i].toString().equals(Action_Enum.setVariable.toString()))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
|
items.add(new Item(typesLong[i].toString(), R.drawable.variable));
|
||||||
else if(types[i].toString().equals(Action_Enum.setLocationService.toString()))
|
else if(types[i].toString().equals(Action_Enum.setLocationService.toString()))
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.compass_small));
|
items.add(new Item(typesLong[i].toString(), R.drawable.compass_small));
|
||||||
|
else if(types[i].toString().equals(Action_Enum.takeScreenshot.toString()))
|
||||||
|
{
|
||||||
|
if(ActivityPermissions.isPermissionDeclaratedInManifest(ActivityManageRule.this, Manifest.permission.BIND_ACCESSIBILITY_SERVICE))
|
||||||
|
items.add(new Item(typesLong[i].toString(), R.drawable.copier));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
|
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.jens.automation2;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.BatteryManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.jens.automation2.ActivityManageRule;
|
||||||
|
import com.jens.automation2.Miscellaneous;
|
||||||
|
import com.jens.automation2.R;
|
||||||
|
import com.jens.automation2.Trigger;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
public class ActivityManageTriggerCharging extends Activity
|
||||||
|
{
|
||||||
|
RadioButton rbChargingOn, rbChargingOff, rbChargingTypeAny, rbChargingTypeAc, rbChargingTypeUsb, rbChargingTypeWireless;
|
||||||
|
Button bTriggerChargingSave;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Miscellaneous.setDisplayLanguage(this);
|
||||||
|
setContentView(R.layout.activity_manage_trigger_charging);
|
||||||
|
|
||||||
|
rbChargingOn = (RadioButton) findViewById(R.id.rbChargingOn);
|
||||||
|
rbChargingOff = (RadioButton) findViewById(R.id.rbChargingOff);
|
||||||
|
rbChargingTypeAny = (RadioButton) findViewById(R.id.rbChargingTypeAny);
|
||||||
|
rbChargingTypeAc = (RadioButton) findViewById(R.id.rbChargingTypeAc);
|
||||||
|
rbChargingTypeUsb = (RadioButton) findViewById(R.id.rbChargingTypeUsb);
|
||||||
|
rbChargingTypeWireless = (RadioButton) findViewById(R.id.rbChargingTypeWireless);
|
||||||
|
|
||||||
|
bTriggerChargingSave = (Button) findViewById(R.id.bTriggerChargingSave);
|
||||||
|
|
||||||
|
Intent input = getIntent();
|
||||||
|
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
|
||||||
|
{
|
||||||
|
|
||||||
|
rbChargingOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
|
||||||
|
rbChargingOff.setChecked(!input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, false));
|
||||||
|
|
||||||
|
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
|
||||||
|
{
|
||||||
|
|
||||||
|
String[] params2 = input.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split);
|
||||||
|
int chargingType = Integer.parseInt(params2[0]);
|
||||||
|
|
||||||
|
rbChargingTypeAny.setChecked(chargingType == 0);
|
||||||
|
rbChargingTypeAc.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_AC);
|
||||||
|
rbChargingTypeUsb.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_USB);
|
||||||
|
rbChargingTypeWireless.setChecked(chargingType == BatteryManager.BATTERY_PLUGGED_WIRELESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bTriggerChargingSave.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View view)
|
||||||
|
{
|
||||||
|
Intent response = new Intent();
|
||||||
|
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbChargingOn.isChecked());
|
||||||
|
|
||||||
|
String param2 = "";
|
||||||
|
|
||||||
|
if(rbChargingTypeAny.isChecked())
|
||||||
|
param2 = "0";
|
||||||
|
else if(rbChargingTypeAc.isChecked())
|
||||||
|
param2 = String.valueOf(BatteryManager.BATTERY_PLUGGED_AC);
|
||||||
|
else if(rbChargingTypeUsb.isChecked())
|
||||||
|
param2 = String.valueOf(BatteryManager.BATTERY_PLUGGED_USB);
|
||||||
|
else if(rbChargingTypeWireless.isChecked())
|
||||||
|
param2 = String.valueOf(BatteryManager.BATTERY_PLUGGED_WIRELESS);
|
||||||
|
|
||||||
|
response.putExtra(ActivityManageRule.intentNameTriggerParameter2, param2);
|
||||||
|
|
||||||
|
setResult(RESULT_OK, response);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -320,8 +320,10 @@ public class AutomationService extends Service implements OnInitListener
|
|||||||
|
|
||||||
ReceiverCoordinator.applySettingsAndRules();
|
ReceiverCoordinator.applySettingsAndRules();
|
||||||
|
|
||||||
DateTimeListener.reloadAlarms();
|
DateTimeListener.setOrResetAlarms();
|
||||||
CalendarReceiver.armOrRearmTimer();
|
|
||||||
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaratedInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
|
||||||
|
CalendarReceiver.armOrRearmTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -585,7 +585,45 @@ public class Miscellaneous extends Service
|
|||||||
|
|
||||||
Miscellaneous.logEvent("i", "TimeCompare", "Default return code. Shouldn't be here.", 5);
|
Miscellaneous.logEvent("i", "TimeCompare", "Default return code. Shouldn't be here.", 5);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int compareTimes(Calendar calOne, Calendar calTwo)
|
||||||
|
{
|
||||||
|
if(calOne.get(Calendar.HOUR_OF_DAY) == calTwo.get(Calendar.HOUR_OF_DAY) && calOne.get(Calendar.MINUTE) == calTwo.get((Calendar.MINUTE)))
|
||||||
|
{
|
||||||
|
// Miscellaneous.logEvent("i", "TimeCompare", "Times are equal.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calOne.get(Calendar.HOUR_OF_DAY) > calTwo.get(Calendar.HOUR_OF_DAY))
|
||||||
|
{
|
||||||
|
// Miscellaneous.logEvent("i", "TimeCompare", "Time1 is bigger/later by hours.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calOne.get(Calendar.HOUR_OF_DAY) < calTwo.get(Calendar.HOUR_OF_DAY))
|
||||||
|
{
|
||||||
|
// Miscellaneous.logEvent("i", "TimeCompare", "Time2 is bigger/later by hours.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calOne.get(Calendar.HOUR_OF_DAY) == calTwo.get(Calendar.HOUR_OF_DAY))
|
||||||
|
{
|
||||||
|
if(calOne.get(Calendar.MINUTE) < calTwo.get(Calendar.MINUTE))
|
||||||
|
{
|
||||||
|
// Miscellaneous.logEvent("i", "TimeCompare", "Hours are equal. Time2 is bigger/later by minutes.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calOne.get(Calendar.MINUTE) > calTwo.get(Calendar.MINUTE))
|
||||||
|
{
|
||||||
|
// Miscellaneous.logEvent("i", "TimeCompare", "Hours are equal. Time1 is bigger/later by minutes.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Miscellaneous.logEvent("i", "TimeCompare", "Default return code. Shouldn't be here.", 5);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String convertStreamToString(InputStream is)
|
public static String convertStreamToString(InputStream is)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.jens.automation2;
|
package com.jens.automation2;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -212,7 +213,7 @@ public class ReceiverCoordinator
|
|||||||
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.screenState))
|
||||||
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
|
ScreenStateReceiver.startScreenStateReceiver(AutomationService.getInstance());
|
||||||
|
|
||||||
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent))
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaratedInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
|
||||||
CalendarReceiver.startCalendarReceiver(AutomationService.getInstance());
|
CalendarReceiver.startCalendarReceiver(AutomationService.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,6 +470,19 @@ public class ReceiverCoordinator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.calendarEvent) && ActivityPermissions.isPermissionDeclaratedInManifest(AutomationService.getInstance(), Manifest.permission.READ_CALENDAR) && ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, AutomationService.getInstance()))
|
||||||
|
{
|
||||||
|
if(!CalendarReceiver.getInstance().isListenerRunning())
|
||||||
|
CalendarReceiver.getInstance().startListener(AutomationService.getInstance());
|
||||||
|
else
|
||||||
|
CalendarReceiver.armOrRearmTimer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(CalendarReceiver.getInstance().isListenerRunning())
|
||||||
|
CalendarReceiver.getInstance().stopListener(AutomationService.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
AutomationService.updateNotification();
|
AutomationService.updateNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.jens.automation2;
|
|||||||
|
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public class TimeFrame
|
public class TimeFrame
|
||||||
{
|
{
|
||||||
@ -20,18 +21,19 @@ public class TimeFrame
|
|||||||
public void setDayList(ArrayList<Integer> dayList)
|
public void setDayList(ArrayList<Integer> dayList)
|
||||||
{
|
{
|
||||||
this.dayList = dayList;
|
this.dayList = dayList;
|
||||||
|
Collections.sort(dayList);
|
||||||
}
|
}
|
||||||
public void setDayListFromString(String dayListString)
|
public void setDayListFromString(String dayListString)
|
||||||
{
|
{
|
||||||
// Log.i("Parsing", "Full string: " + dayListString);
|
|
||||||
char[] dayListCharArray = dayListString.toCharArray();
|
char[] dayListCharArray = dayListString.toCharArray();
|
||||||
|
|
||||||
dayList = new ArrayList<Integer>();
|
dayList = new ArrayList<Integer>();
|
||||||
for(char item : dayListCharArray)
|
for(char item : dayListCharArray)
|
||||||
{
|
{
|
||||||
// Log.i("Parsing", String.valueOf(item));
|
|
||||||
dayList.add(Integer.parseInt(String.valueOf(item)));
|
dayList.add(Integer.parseInt(String.valueOf(item)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collections.sort(dayList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeObject getTriggerTimeStart()
|
public TimeObject getTriggerTimeStart()
|
||||||
|
@ -2,6 +2,7 @@ package com.jens.automation2;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.BatteryManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
@ -16,6 +17,7 @@ import com.jens.automation2.receivers.BluetoothReceiver;
|
|||||||
import com.jens.automation2.receivers.BroadcastListener;
|
import com.jens.automation2.receivers.BroadcastListener;
|
||||||
import com.jens.automation2.receivers.CalendarReceiver;
|
import com.jens.automation2.receivers.CalendarReceiver;
|
||||||
import com.jens.automation2.receivers.ConnectivityReceiver;
|
import com.jens.automation2.receivers.ConnectivityReceiver;
|
||||||
|
import com.jens.automation2.receivers.DateTimeListener;
|
||||||
import com.jens.automation2.receivers.DeviceOrientationListener;
|
import com.jens.automation2.receivers.DeviceOrientationListener;
|
||||||
import com.jens.automation2.receivers.HeadphoneJackListener;
|
import com.jens.automation2.receivers.HeadphoneJackListener;
|
||||||
import com.jens.automation2.receivers.MediaPlayerListener;
|
import com.jens.automation2.receivers.MediaPlayerListener;
|
||||||
@ -134,6 +136,35 @@ public class Trigger
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boolean triggerParameter; //if true->started event, if false->stopped
|
||||||
|
String triggerParameter2;
|
||||||
|
|
||||||
|
public static final String triggerParameter2Split = "tp2split";
|
||||||
|
|
||||||
|
Trigger_Enum triggerType = null;
|
||||||
|
PointOfInterest pointOfInterest = null;
|
||||||
|
TimeFrame timeFrame;
|
||||||
|
|
||||||
|
public static String triggerPhoneCallStateRinging = "ringing";
|
||||||
|
public static String triggerPhoneCallStateStarted = "started";
|
||||||
|
public static String triggerPhoneCallStateStopped = "stopped";
|
||||||
|
public static String triggerPhoneCallDirectionIncoming = "incoming";
|
||||||
|
public static String triggerPhoneCallDirectionOutgoing = "outgoing";
|
||||||
|
public static String triggerPhoneCallDirectionAny = "any";
|
||||||
|
public static String triggerPhoneCallNumberAny = "any";
|
||||||
|
|
||||||
|
double speed; //km/h
|
||||||
|
long noiseLevelDb;
|
||||||
|
String processName = null;
|
||||||
|
int batteryLevel;
|
||||||
|
int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
|
||||||
|
String phoneNumber = null;
|
||||||
|
String nfcTagId = null;
|
||||||
|
String bluetoothEvent = null;
|
||||||
|
String bluetoothDeviceAddress = null;
|
||||||
|
int activityDetectionType = -1;
|
||||||
|
int headphoneType = -1;
|
||||||
|
|
||||||
public static enum subSystemStates { wifi, bluetooth };
|
public static enum subSystemStates { wifi, bluetooth };
|
||||||
|
|
||||||
Rule parentRule = null;
|
Rule parentRule = null;
|
||||||
@ -1123,8 +1154,6 @@ public class Trigger
|
|||||||
// We are not at any POI. But if this trigger requires us NOT to be there, that may be fine.
|
// We are not at any POI. But if this trigger requires us NOT to be there, that may be fine.
|
||||||
if(this.getPointOfInterest() != null)
|
if(this.getPointOfInterest() != null)
|
||||||
{
|
{
|
||||||
// if(activePoi.equals(oneTrigger.getPointOfInterest()))
|
|
||||||
// {
|
|
||||||
if(!this.getTriggerParameter())
|
if(!this.getTriggerParameter())
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "We are not at POI \"" + this.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4);
|
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "We are not at POI \"" + this.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4);
|
||||||
@ -1134,7 +1163,6 @@ public class Trigger
|
|||||||
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", getParentRule().getName()), 3);
|
Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format("Rule \"%1$s\" doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", getParentRule().getName()), 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
else if(this.getPointOfInterest() == null)
|
else if(this.getPointOfInterest() == null)
|
||||||
{
|
{
|
||||||
@ -1171,22 +1199,34 @@ public class Trigger
|
|||||||
|
|
||||||
boolean checkCharging()
|
boolean checkCharging()
|
||||||
{
|
{
|
||||||
if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0)
|
if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0) // unknown state
|
||||||
{
|
{
|
||||||
return false; // unknown charging state, can't activate rule under these conditions
|
return false; // unknown charging state, can't activate rule under these conditions
|
||||||
}
|
}
|
||||||
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1)
|
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1) // we are discharging
|
||||||
{
|
{
|
||||||
if(this.getTriggerParameter()) //rule says when charging, but we're currently discharging
|
if(!this.getTriggerParameter()) // rule says when charging, but we're currently discharging
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2)
|
else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2) // we are charging
|
||||||
{
|
{
|
||||||
if(!this.getTriggerParameter()) //rule says when discharging, but we're currently charging
|
if(this.getTriggerParameter()) // rule says when discharging, but we're currently charging
|
||||||
return false;
|
{
|
||||||
|
// check charging type
|
||||||
|
if(StringUtils.isEmpty(getTriggerParameter2()))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int desiredType;
|
||||||
|
String[] typeParams = getTriggerParameter2().split(triggerParameter2Split, -1);
|
||||||
|
desiredType = Integer.parseInt(typeParams[0]);
|
||||||
|
if(desiredType == BatteryReceiver.getCurrentChargingType())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkTetheringActive()
|
boolean checkTetheringActive()
|
||||||
@ -1211,7 +1251,7 @@ public class Trigger
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution)
|
public boolean checkDateTime(Object triggeringObject, boolean checkIfStateChangedSinceLastRuleExecution)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Use format known from Automation
|
* Use format known from Automation
|
||||||
@ -1233,142 +1273,52 @@ public class Trigger
|
|||||||
{
|
{
|
||||||
TimeFrame tf = new TimeFrame(getTriggerParameter2());
|
TimeFrame tf = new TimeFrame(getTriggerParameter2());
|
||||||
|
|
||||||
if(tf.getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK)))
|
if (DateTimeListener.areWeInTimeFrame(this, triggeringObject) != this.getTriggerParameter())
|
||||||
{
|
{
|
||||||
if(
|
if (triggerParameter)
|
||||||
// Regular case, start time is lower than end time
|
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") outside of the specified TimeFrame (" + tf.toString() + "), but demanded is inside.", 5);
|
||||||
(
|
else
|
||||||
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
|
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + tf.toString() + "), but demanded is outside.", 4);
|
||||||
&&
|
|
||||||
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0
|
return false;
|
||||||
)
|
}
|
||||||
||
|
|
||||||
// Other case, start time higher than end time, timeframe goes over midnight
|
// We are inside or outside of the timeframe as demanded by the trigger
|
||||||
(
|
|
||||||
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) < 0
|
if (tf.getRepetition() > 0)
|
||||||
&&
|
{
|
||||||
(Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
|
if (!isSupposedToRepeatSinceLastExecution(Calendar.getInstance()))
|
||||||
||
|
|
||||||
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0)
|
|
||||||
)
|
|
||||||
||
|
|
||||||
// further case: start and end times are identical, meaning a 24h window
|
|
||||||
(
|
|
||||||
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) == 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// We are in the timeframe
|
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repetition is not due, yet.", 4);
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + tf.toString() + ").", 4);
|
return false;
|
||||||
if(getTriggerParameter())
|
|
||||||
{
|
|
||||||
if(checkifStateChangedSinceLastRuleExecution)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Was there a target repetition time between last execution and now?
|
|
||||||
* If not -> return false.
|
|
||||||
*/
|
|
||||||
Calendar compareCal = Calendar.getInstance();
|
|
||||||
compareCal.setTimeInMillis(triggeringTime.getTime());
|
|
||||||
if(tf.getRepetition() > 0)
|
|
||||||
{
|
|
||||||
if(!isSupposedToRepeatSinceLastExecution(compareCal))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repeated execution is not due, yet.", 4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* This is not a repeating rule. Have we left
|
|
||||||
* the relevant timeframe since the last run?
|
|
||||||
* Determine if it has ran today already. If yes
|
|
||||||
* return false because every rule that is not
|
|
||||||
* repeating can only be executed once per day.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(
|
|
||||||
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
|
|
||||||
&&
|
|
||||||
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
|
|
||||||
&&
|
|
||||||
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's what's specified. Trigger of rule " + this.getParentRule().getName() + " applies.", 4);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's not what's specified. Trigger of rule " + this.getParentRule().getName() + " doesn't apply.", 4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " would apply because repetition is due.", 4);
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + tf.toString() + ") because of the time.", 5);
|
|
||||||
if(!getTriggerParameter())
|
|
||||||
{
|
|
||||||
if(checkifStateChangedSinceLastRuleExecution)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Was there a target repetition time between last execution and now?
|
|
||||||
* If not -> return false.
|
|
||||||
*/
|
|
||||||
Calendar compareCal = Calendar.getInstance();
|
|
||||||
compareCal.setTimeInMillis(triggeringTime.getTime());
|
|
||||||
if(tf.getRepetition() > 0)
|
|
||||||
{
|
|
||||||
if(!isSupposedToRepeatSinceLastExecution(compareCal))
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but repeated execution is not due, yet.", 4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* This is not a repeating rule. Have we left
|
|
||||||
* the relevant timeframe since the last run?
|
|
||||||
* Determine if it has ran today already. If yes
|
|
||||||
* return false because every rule that is not
|
|
||||||
* repeating can only be executed once per day.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(
|
|
||||||
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
|
|
||||||
&&
|
|
||||||
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
|
|
||||||
&&
|
|
||||||
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's what's specified. Trigger of rule " + this.getParentRule().getName() + " applies.", 5);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: That's not what's specified. Trigger of rule " + this.getParentRule().getName() + " doesn't apply.", 5);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "Trigger", "TimeFrame: We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + tf.toString() + ") because of the day.", 5);
|
if (checkIfStateChangedSinceLastRuleExecution)
|
||||||
return false;
|
{
|
||||||
|
/*
|
||||||
|
* This is not a repeating rule. Have we left
|
||||||
|
* the relevant timeframe since the last run?
|
||||||
|
* Determine if it has ran today already. If yes
|
||||||
|
* return false because every rule that is not
|
||||||
|
* repeating can only be executed once per day.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (
|
||||||
|
getParentRule().getLastExecution().get(Calendar.YEAR) == calNow.get(Calendar.YEAR)
|
||||||
|
&&
|
||||||
|
getParentRule().getLastExecution().get(Calendar.MONTH) == calNow.get(Calendar.MONTH)
|
||||||
|
&&
|
||||||
|
getParentRule().getLastExecution().get(Calendar.DAY_OF_MONTH) == calNow.get(Calendar.DAY_OF_MONTH)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "TimeFrame", "TimeFrame: Trigger of rule " + this.getParentRule().getName() + " applies, but it was already executed today.", 4);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
@ -1376,43 +1326,8 @@ public class Trigger
|
|||||||
Miscellaneous.logEvent("e", "Trigger", "There was an error while checking if the time based trigger applies: " + Log.getStackTraceString(e), 1);
|
Miscellaneous.logEvent("e", "Trigger", "There was an error while checking if the time based trigger applies: " + Log.getStackTraceString(e), 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
|
return true;
|
||||||
{
|
|
||||||
Calendar calSet;
|
|
||||||
TimeObject setTime;
|
|
||||||
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
|
|
||||||
|
|
||||||
if(tf.getRepetition() > 0)
|
|
||||||
{
|
|
||||||
if(trigger.getTriggerParameter())
|
|
||||||
setTime = tf.getTriggerTimeStart();
|
|
||||||
else
|
|
||||||
setTime = tf.getTriggerTimeStop();
|
|
||||||
|
|
||||||
calSet = (Calendar) now.clone();
|
|
||||||
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
|
||||||
calSet.set(Calendar.MINUTE, setTime.getMinutes());
|
|
||||||
calSet.set(Calendar.SECOND, 0);
|
|
||||||
calSet.set(Calendar.MILLISECOND, 0);
|
|
||||||
|
|
||||||
// If the starting time is a day ahead remove 1 day.
|
|
||||||
if(calSet.getTimeInMillis() > now.getTimeInMillis())
|
|
||||||
calSet.add(Calendar.DAY_OF_MONTH, -1);
|
|
||||||
|
|
||||||
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calSet.getTimeInMillis()) / 1000;
|
|
||||||
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
|
|
||||||
long nextScheduleTimestamp = (calSet.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition());
|
|
||||||
Calendar calSchedule = Calendar.getInstance();
|
|
||||||
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
|
|
||||||
|
|
||||||
return calSchedule;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Miscellaneous.logEvent("i", "Trigger", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isSupposedToRepeatSinceLastExecution(Calendar now)
|
boolean isSupposedToRepeatSinceLastExecution(Calendar now)
|
||||||
@ -1422,7 +1337,7 @@ public class Trigger
|
|||||||
|
|
||||||
// the simple stuff:
|
// the simple stuff:
|
||||||
|
|
||||||
if(lastExec == null) // rule never run, go any way
|
if(lastExec == null) // rule never ran, go in any case
|
||||||
return true;
|
return true;
|
||||||
else if(tf.getRepetition() <= 0) // is not set to repeat at all
|
else if(tf.getRepetition() <= 0) // is not set to repeat at all
|
||||||
return false;
|
return false;
|
||||||
@ -1433,41 +1348,17 @@ public class Trigger
|
|||||||
* we're inside the specified timeframe.
|
* we're inside the specified timeframe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Calendar timeSupposedToRunNext = getNextRepeatedExecutionAfter(this, lastExec);
|
Calendar lastRepetitionNotExecutedYet = DateTimeListener.getNextRepeatedExecution(this);
|
||||||
if(now.getTimeInMillis() > timeSupposedToRunNext.getTimeInMillis())
|
lastRepetitionNotExecutedYet.add(Calendar.SECOND, (int) -(tf.getRepetition()));
|
||||||
|
|
||||||
|
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "Last execution: " + Miscellaneous.formatDate(lastExec.getTime()), 5);
|
||||||
|
Miscellaneous.logEvent("i", "isSupposedToRepeatSinceLastExecution()", "lastRepetitionNotExecutedYet: " + Miscellaneous.formatDate(lastRepetitionNotExecutedYet.getTime()), 5);
|
||||||
|
|
||||||
|
if(now.getTimeInMillis() > lastRepetitionNotExecutedYet.getTimeInMillis())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean triggerParameter; //if true->started event, if false->stopped
|
|
||||||
String triggerParameter2;
|
|
||||||
|
|
||||||
public static final String triggerParameter2Split = "tp2split";
|
|
||||||
|
|
||||||
Trigger_Enum triggerType = null;
|
|
||||||
PointOfInterest pointOfInterest = null;
|
|
||||||
TimeFrame timeFrame;
|
|
||||||
|
|
||||||
public static String triggerPhoneCallStateRinging = "ringing";
|
|
||||||
public static String triggerPhoneCallStateStarted = "started";
|
|
||||||
public static String triggerPhoneCallStateStopped = "stopped";
|
|
||||||
public static String triggerPhoneCallDirectionIncoming = "incoming";
|
|
||||||
public static String triggerPhoneCallDirectionOutgoing = "outgoing";
|
|
||||||
public static String triggerPhoneCallDirectionAny = "any";
|
|
||||||
public static String triggerPhoneCallNumberAny = "any";
|
|
||||||
|
|
||||||
double speed; //km/h
|
|
||||||
long noiseLevelDb;
|
|
||||||
String processName = null;
|
|
||||||
int batteryLevel;
|
|
||||||
int phoneDirection = 0; // 0=any, 1=incoming, 2=outgoing
|
|
||||||
String phoneNumber = null;
|
|
||||||
String nfcTagId = null;
|
|
||||||
String bluetoothEvent = null;
|
|
||||||
String bluetoothDeviceAddress = null;
|
|
||||||
int activityDetectionType = -1;
|
|
||||||
int headphoneType = -1;
|
|
||||||
|
|
||||||
public int getHeadphoneType()
|
public int getHeadphoneType()
|
||||||
{
|
{
|
||||||
@ -1625,6 +1516,20 @@ public class Trigger
|
|||||||
else
|
else
|
||||||
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.stopping) + " ");
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.stopping) + " ");
|
||||||
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.triggerCharging));
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.triggerCharging));
|
||||||
|
returnString.append(" (");
|
||||||
|
if(!StringUtils.isEmpty(getTriggerParameter2()))
|
||||||
|
{
|
||||||
|
String[] pieces = getTriggerParameter2().split(triggerParameter2Split, -1);
|
||||||
|
if(pieces[0].equals("0"))
|
||||||
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.any));
|
||||||
|
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_AC)))
|
||||||
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.charging_AC));
|
||||||
|
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_USB)))
|
||||||
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.usb));
|
||||||
|
else if(pieces[0].equals(String.valueOf(BatteryManager.BATTERY_PLUGGED_WIRELESS)))
|
||||||
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.charging_wireless));
|
||||||
|
}
|
||||||
|
returnString.append(")");
|
||||||
break;
|
break;
|
||||||
case batteryLevel:
|
case batteryLevel:
|
||||||
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.batteryLevel));
|
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.batteryLevel));
|
||||||
|
@ -7,7 +7,6 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.jens.automation2.ActivityPermissions;
|
import com.jens.automation2.ActivityPermissions;
|
||||||
import com.jens.automation2.AutomationService;
|
import com.jens.automation2.AutomationService;
|
||||||
@ -25,6 +24,9 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
static boolean batteryReceiverActive = false;
|
static boolean batteryReceiverActive = false;
|
||||||
static IntentFilter batteryIntentFilter = null;
|
static IntentFilter batteryIntentFilter = null;
|
||||||
static Intent batteryStatus = null;
|
static Intent batteryStatus = null;
|
||||||
|
|
||||||
|
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
|
||||||
|
private static int currentChargingType = 0; //AC, wireless, USB
|
||||||
static BroadcastReceiver batteryInfoReceiverInstance = null;
|
static BroadcastReceiver batteryInfoReceiverInstance = null;
|
||||||
|
|
||||||
public static void startBatteryReceiver(final AutomationService automationServiceRef)
|
public static void startBatteryReceiver(final AutomationService automationServiceRef)
|
||||||
@ -41,8 +43,6 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
batteryIntentFilter = new IntentFilter();
|
batteryIntentFilter = new IntentFilter();
|
||||||
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||||
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||||
// batteryIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
|
|
||||||
// batteryIntentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
batteryStatus = automationServiceRef.registerReceiver(batteryInfoReceiverInstance, batteryIntentFilter);
|
batteryStatus = automationServiceRef.registerReceiver(batteryInfoReceiverInstance, batteryIntentFilter);
|
||||||
@ -79,8 +79,6 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
return batteryLevel;
|
return batteryLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
|
|
||||||
|
|
||||||
public static int getCurrentChargingState()
|
public static int getCurrentChargingState()
|
||||||
{
|
{
|
||||||
return currentChargingState;
|
return currentChargingState;
|
||||||
@ -123,7 +121,12 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
case BatteryManager.BATTERY_PLUGGED_AC:
|
case BatteryManager.BATTERY_PLUGGED_AC:
|
||||||
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
|
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
|
||||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.", 5);
|
Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.", 5);
|
||||||
this.actionCharging(context);
|
this.actionCharging(context, statusPlugged);
|
||||||
|
break;
|
||||||
|
case BatteryManager.BATTERY_PLUGGED_WIRELESS:
|
||||||
|
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
|
||||||
|
Miscellaneous.logEvent("i", "BatteryReceiver", "Wireless charging.", 5);
|
||||||
|
this.actionCharging(context, statusPlugged);
|
||||||
break;
|
break;
|
||||||
case BatteryManager.BATTERY_PLUGGED_USB:
|
case BatteryManager.BATTERY_PLUGGED_USB:
|
||||||
this.actionUsbConnected(context);
|
this.actionUsbConnected(context);
|
||||||
@ -135,7 +138,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
case BatteryManager.BATTERY_STATUS_CHARGING:
|
case BatteryManager.BATTERY_STATUS_CHARGING:
|
||||||
case BatteryManager.BATTERY_STATUS_FULL:
|
case BatteryManager.BATTERY_STATUS_FULL:
|
||||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.", 5);
|
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.", 5);
|
||||||
this.actionCharging(context);
|
this.actionCharging(context, statusPlugged);
|
||||||
break;
|
break;
|
||||||
case BatteryManager.BATTERY_STATUS_DISCHARGING:
|
case BatteryManager.BATTERY_STATUS_DISCHARGING:
|
||||||
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
|
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
|
||||||
@ -155,28 +158,33 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
switch(currentChargingState)
|
switch(currentChargingState)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
Miscellaneous.logEvent("w", "ChargingInfo", "Status of device charging was requested. Information isn't available, yet.", 4);
|
Miscellaneous.logEvent("w", "ChargingInfo", "Information isn't available, yet.", 4);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is discharging.", 3);
|
Miscellaneous.logEvent("i", "ChargingInfo", "Device is discharging.", 3);
|
||||||
break;
|
break;
|
||||||
case BatteryManager.BATTERY_STATUS_CHARGING:
|
case BatteryManager.BATTERY_STATUS_CHARGING:
|
||||||
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is charging.", 3);
|
Miscellaneous.logEvent("i", "ChargingInfo", "Device is charging.", 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentChargingState;
|
return currentChargingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void actionCharging(Context context)
|
public static int getCurrentChargingType()
|
||||||
|
{
|
||||||
|
return currentChargingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionCharging(Context context, int statusPlugged)
|
||||||
{
|
{
|
||||||
if(currentChargingState != BatteryManager.BATTERY_STATUS_CHARGING) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
|
if(currentChargingState != BatteryManager.BATTERY_STATUS_CHARGING) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.", 3);
|
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.", 3);
|
||||||
currentChargingState = BatteryManager.BATTERY_STATUS_CHARGING;
|
currentChargingState = BatteryManager.BATTERY_STATUS_CHARGING;
|
||||||
//activate rule(s)
|
currentChargingType = statusPlugged;
|
||||||
|
|
||||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
|
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.charging);
|
||||||
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
|
|
||||||
for(int i=0; i<ruleCandidates.size(); i++)
|
for(int i=0; i<ruleCandidates.size(); i++)
|
||||||
{
|
{
|
||||||
if(ruleCandidates.get(i).getsGreenLight(context))
|
if(ruleCandidates.get(i).getsGreenLight(context))
|
||||||
@ -229,14 +237,13 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
|
|||||||
// Toast.makeText(context, "Connected to computer.", Toast.LENGTH_LONG).show();
|
// Toast.makeText(context, "Connected to computer.", Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.usb_host_connection);
|
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger_Enum.usb_host_connection);
|
||||||
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(true);
|
|
||||||
for(Rule oneRule : ruleCandidates)
|
for(Rule oneRule : ruleCandidates)
|
||||||
{
|
{
|
||||||
if(oneRule.getsGreenLight(context))
|
if(oneRule.getsGreenLight(context))
|
||||||
oneRule.activate(automationServiceRef, false);
|
oneRule.activate(automationServiceRef, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.actionCharging(context);
|
this.actionCharging(context, BatteryManager.BATTERY_PLUGGED_USB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ import android.content.Intent;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import com.jens.automation2.AutomationService;
|
import com.jens.automation2.AutomationService;
|
||||||
import com.jens.automation2.BuildConfig;
|
|
||||||
import com.jens.automation2.Miscellaneous;
|
import com.jens.automation2.Miscellaneous;
|
||||||
import com.jens.automation2.Rule;
|
import com.jens.automation2.Rule;
|
||||||
import com.jens.automation2.TimeFrame;
|
import com.jens.automation2.TimeFrame;
|
||||||
@ -19,23 +19,23 @@ import com.jens.automation2.TimeObject;
|
|||||||
import com.jens.automation2.Trigger;
|
import com.jens.automation2.Trigger;
|
||||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||||
|
|
||||||
import java.sql.Time;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class DateTimeListener extends BroadcastReceiver implements AutomationListenerInterface
|
public class DateTimeListener extends BroadcastReceiver implements AutomationListenerInterface
|
||||||
{
|
{
|
||||||
private static AutomationService automationServiceRef;
|
private static AutomationService automationServiceRef;
|
||||||
private static AlarmManager centralAlarmManagerInstance;
|
private static AlarmManager centralAlarmManagerInstance;
|
||||||
private static boolean alarmListenerActive = false;
|
private static boolean alarmListenerActive=false;
|
||||||
private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>();
|
private static ArrayList<ScheduleElement> alarmCandidates = new ArrayList<>();
|
||||||
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
|
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
|
||||||
static PendingIntent alarmPendingIntent = null;
|
static PendingIntent alarmPendingIntent = null;
|
||||||
|
|
||||||
public static void startAlarmListener(final AutomationService automationServiceRef)
|
public static void startAlarmListener(final AutomationService automationServiceRef)
|
||||||
{
|
{
|
||||||
DateTimeListener.startAlarmListenerInternal(automationServiceRef);
|
DateTimeListener.startAlarmListenerInternal(automationServiceRef);
|
||||||
}
|
}
|
||||||
public static void stopAlarmListener(Context context)
|
public static void stopAlarmListener(Context context)
|
||||||
@ -47,37 +47,37 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
{
|
{
|
||||||
return alarmListenerActive;
|
return alarmListenerActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent)
|
public void onReceive(Context context, Intent intent)
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
|
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
|
||||||
|
|
||||||
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
|
ArrayList<Rule> allRulesWithTimeFrame = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
|
||||||
for(int i=0; i < allRulesWithNowInTimeFrame.size(); i++)
|
for(int i=0; i < allRulesWithTimeFrame.size(); i++)
|
||||||
{
|
{
|
||||||
if(allRulesWithNowInTimeFrame.get(i).getsGreenLight(context))
|
if(allRulesWithTimeFrame.get(i).getsGreenLight(context))
|
||||||
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
|
allRulesWithTimeFrame.get(i).activate(automationServiceRef, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAlarms();
|
setOrResetAlarms();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
public static void setAlarms()
|
public static void setOrResetAlarms()
|
||||||
{
|
{
|
||||||
alarmCandidates.clear();
|
alarmCandidates.clear();
|
||||||
|
|
||||||
Calendar calNow = Calendar.getInstance();
|
Calendar calNow = Calendar.getInstance();
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
||||||
|
|
||||||
clearAlarms();
|
clearAlarms();
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
|
|
||||||
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
|
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
|
||||||
allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
|
allRulesWithTimeFrames = Rule.findRuleCandidates(Trigger_Enum.timeFrame);
|
||||||
// allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame();
|
|
||||||
/*
|
/*
|
||||||
* Take care of regular executions, no repetitions in between.
|
* Take care of regular executions, no repetitions in between.
|
||||||
*/
|
*/
|
||||||
@ -191,18 +191,17 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
* 4. Take div result +1 and add this on top of starting time
|
* 4. Take div result +1 and add this on top of starting time
|
||||||
* 5. Is this next possible execution still inside timeframe? Also consider timeframes spanning over midnight
|
* 5. Is this next possible execution still inside timeframe? Also consider timeframes spanning over midnight
|
||||||
*/
|
*/
|
||||||
Calendar calSet;
|
|
||||||
Time setTime;
|
|
||||||
TimeFrame tf = new TimeFrame(oneTrigger.getTriggerParameter2());
|
TimeFrame tf = new TimeFrame(oneTrigger.getTriggerParameter2());
|
||||||
|
|
||||||
if(tf.getRepetition() > 0)
|
if(tf.getRepetition() > 0)
|
||||||
{
|
{
|
||||||
if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext()))
|
// if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext()))
|
||||||
{
|
// {
|
||||||
Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow);
|
Calendar calSchedule = getNextRepeatedExecution(oneTrigger);
|
||||||
|
|
||||||
alarmCandidates.add(new ScheduleElement(calSchedule, "Rule " + oneRule.getName() + ", trigger " + oneTrigger.toString()));
|
alarmCandidates.add(new ScheduleElement(calSchedule, "Rule " + oneRule.getName() + ", trigger " + oneTrigger.toString()));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,15 +212,15 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleNextAlarm();
|
scheduleNextAlarm();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleNextAlarm()
|
private static void scheduleNextAlarm()
|
||||||
{
|
{
|
||||||
Long currentTime = System.currentTimeMillis();
|
Long currentTime = System.currentTimeMillis();
|
||||||
ScheduleElement scheduleCandidate = null;
|
ScheduleElement scheduleCandidate = null;
|
||||||
|
|
||||||
if(alarmCandidates.size() == 0)
|
if(alarmCandidates.size() == 0)
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
|
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
|
||||||
@ -235,46 +234,48 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
else if(alarmCandidates.size() > 1)
|
else if(alarmCandidates.size() > 1)
|
||||||
{
|
{
|
||||||
scheduleCandidate = alarmCandidates.get(0);
|
scheduleCandidate = alarmCandidates.get(0);
|
||||||
|
|
||||||
for(ScheduleElement alarmCandidate : alarmCandidates)
|
for(ScheduleElement alarmCandidate : alarmCandidates)
|
||||||
{
|
{
|
||||||
if(Math.abs(currentTime - alarmCandidate.time.getTimeInMillis()) < Math.abs(currentTime - scheduleCandidate.time.getTimeInMillis()))
|
if(Math.abs(currentTime - alarmCandidate.time.getTimeInMillis()) < Math.abs(currentTime - scheduleCandidate.time.getTimeInMillis()))
|
||||||
scheduleCandidate = alarmCandidate;
|
scheduleCandidate = alarmCandidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
|
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
|
||||||
|
|
||||||
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
|
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
|
||||||
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
else
|
else
|
||||||
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||||
centralAlarmManagerInstance.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
|
centralAlarmManagerInstance.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
|
||||||
else
|
else
|
||||||
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
|
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
|
||||||
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm:ss");
|
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm:ss");
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
calendar.setTimeInMillis(scheduleCandidate.time.getTimeInMillis());
|
calendar.setTimeInMillis(scheduleCandidate.time.getTimeInMillis());
|
||||||
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
|
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearAlarms()
|
public static void clearAlarms()
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
|
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
|
||||||
|
|
||||||
for(int requestCode : requestCodeList)
|
for(int requestCode : requestCodeList)
|
||||||
{
|
{
|
||||||
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
|
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
|
||||||
if(alarmPendingIntent == null)
|
if(alarmPendingIntent == null)
|
||||||
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
|
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
|
||||||
// Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode));
|
|
||||||
centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestCodeList.clear();
|
requestCodeList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
|
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
|
||||||
{
|
{
|
||||||
if(!alarmListenerActive)
|
if(!alarmListenerActive)
|
||||||
@ -282,12 +283,11 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
|
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
|
||||||
DateTimeListener.automationServiceRef = givenAutomationServiceRef;
|
DateTimeListener.automationServiceRef = givenAutomationServiceRef;
|
||||||
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
|
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
|
||||||
// alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
|
||||||
// alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, 0);
|
|
||||||
alarmListenerActive = true;
|
alarmListenerActive = true;
|
||||||
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
|
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
|
||||||
DateTimeListener.setAlarms();
|
DateTimeListener.setOrResetAlarms();
|
||||||
|
|
||||||
// // get a Calendar object with current time
|
// // get a Calendar object with current time
|
||||||
// Calendar cal = Calendar.getInstance();
|
// Calendar cal = Calendar.getInstance();
|
||||||
// // add 5 minutes to the calendar object
|
// // add 5 minutes to the calendar object
|
||||||
@ -297,23 +297,20 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
else
|
else
|
||||||
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
|
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void stopAlarmListenerInternal()
|
private static void stopAlarmListenerInternal()
|
||||||
{
|
{
|
||||||
if(alarmListenerActive)
|
if(alarmListenerActive)
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
|
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
|
||||||
clearAlarms();
|
clearAlarms();
|
||||||
// centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
||||||
alarmListenerActive = false;
|
alarmListenerActive = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Miscellaneous.logEvent("i", "AlarmListener", "Request to stop AlarmListener. But it's not running.", 5);
|
Miscellaneous.logEvent("i", "AlarmListener", "Request to stop AlarmListener. But it's not running.", 5);
|
||||||
}
|
}
|
||||||
public static void reloadAlarms()
|
|
||||||
{
|
|
||||||
DateTimeListener.setAlarms();
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public void startListener(AutomationService automationService)
|
public void startListener(AutomationService automationService)
|
||||||
{
|
{
|
||||||
@ -371,46 +368,217 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
static int getNextDayIntForExecution(Trigger trigger)
|
||||||
public static Calendar getNextRepeatedExecutionAfter(Trigger trigger, Calendar now)
|
|
||||||
{
|
{
|
||||||
Calendar calSet;
|
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
|
||||||
TimeObject setTime;
|
Calendar now = Calendar.getInstance();
|
||||||
|
|
||||||
|
if(tf.getDayList().contains(now.get(Calendar.DAY_OF_WEEK)))
|
||||||
|
return now.get(Calendar.DAY_OF_WEEK);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int dayNumberOfNextExecution = now.get(Calendar.DAY_OF_WEEK);
|
||||||
|
|
||||||
|
while(!tf.getDayList().contains(dayNumberOfNextExecution))
|
||||||
|
{
|
||||||
|
dayNumberOfNextExecution++;
|
||||||
|
if(dayNumberOfNextExecution > 6)
|
||||||
|
dayNumberOfNextExecution = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dayNumberOfNextExecution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getDayDelta(Calendar now, int dayNumberOfNextExecution)
|
||||||
|
{
|
||||||
|
int result = dayNumberOfNextExecution - now.get(Calendar.DAY_OF_WEEK);
|
||||||
|
|
||||||
|
if(result >= 0)
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
return 6 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
|
public static Calendar getNextRepeatedExecution(Trigger trigger)
|
||||||
|
{
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
Miscellaneous.logEvent("i", "DateTimeListener", "Checking for next repetition execution after " + Miscellaneous.formatDate(now.getTime()), 5);
|
||||||
|
Calendar calculationStart, calSchedule = null;
|
||||||
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
|
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
|
||||||
|
|
||||||
if(tf.getRepetition() > 0)
|
if(tf.getRepetition() > 0)
|
||||||
{
|
{
|
||||||
if(trigger.getTriggerParameter())
|
|
||||||
setTime = tf.getTriggerTimeStart();
|
|
||||||
else
|
|
||||||
setTime = tf.getTriggerTimeStop();
|
|
||||||
|
|
||||||
calSet = (Calendar) now.clone();
|
|
||||||
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
|
||||||
calSet.set(Calendar.MINUTE, setTime.getMinutes());
|
|
||||||
calSet.set(Calendar.SECOND, 0);
|
|
||||||
calSet.set(Calendar.MILLISECOND, 0);
|
|
||||||
|
|
||||||
// If the starting time is a day ahead remove 1 day.
|
|
||||||
if(calSet.getTimeInMillis() > now.getTimeInMillis())
|
|
||||||
calSet.add(Calendar.DAY_OF_MONTH, -1);
|
|
||||||
|
|
||||||
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calSet.getTimeInMillis()) / 1000;
|
|
||||||
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
|
|
||||||
long nextScheduleTimestamp = (calSet.getTimeInMillis() / 1000) + (nextExecutionMultiplier * tf.getRepetition());
|
|
||||||
Calendar calSchedule = Calendar.getInstance();
|
|
||||||
calSchedule.setTimeInMillis(nextScheduleTimestamp * 1000);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Das war mal aktiviert. Allerdings: Die ganze Funktion liefert zurück, wenn die Regel NOCH nicht
|
Are we inside of the timeframe or outside?
|
||||||
* zutrifft, aber wir z.B. gleich den zeitlichen Bereich betreten.
|
|
||||||
|
Inside -> is this demanded?
|
||||||
|
Yes:
|
||||||
|
If last execution known, calculate from it
|
||||||
|
If not known, calculate from start of timeframe
|
||||||
|
No:
|
||||||
|
Use end-time and add repetition
|
||||||
|
|
||||||
|
Outside? -> is this demanded?
|
||||||
|
Yes:
|
||||||
|
If last execution known, calculate from it
|
||||||
|
If not known, calculate from end of timeframe
|
||||||
|
No:
|
||||||
|
Use start-time and add repetition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return calSchedule;
|
if(areWeInTimeFrame(trigger, new Date()))
|
||||||
|
{
|
||||||
|
if(trigger.getTriggerParameter())
|
||||||
|
{
|
||||||
|
if(trigger.getParentRule().getLastExecution() != null)
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) trigger.getParentRule().getLastExecution().clone();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) now.clone();
|
||||||
|
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStart().getHours());
|
||||||
|
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStart().getMinutes());
|
||||||
|
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStart().getSeconds());
|
||||||
|
calculationStart.set(Calendar.MILLISECOND, 0);
|
||||||
|
}
|
||||||
|
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
|
||||||
|
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) now.clone();
|
||||||
|
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStop().getHours());
|
||||||
|
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStop().getMinutes());
|
||||||
|
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStop().getSeconds());
|
||||||
|
calculationStart.set(Calendar.MILLISECOND, 0);
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
calSchedule.add(Calendar.SECOND, (int) tf.getRepetition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // not in timeframe
|
||||||
|
{
|
||||||
|
if (!trigger.getTriggerParameter())
|
||||||
|
{
|
||||||
|
if (trigger.getParentRule().getLastExecution() != null)
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) trigger.getParentRule().getLastExecution().clone();
|
||||||
|
long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
|
||||||
|
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));
|
||||||
|
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
|
||||||
|
return calSchedule;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) now.clone();
|
||||||
|
if(tf.getDayList().contains(now.get(Calendar.DAY_OF_WEEK)))
|
||||||
|
{
|
||||||
|
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStop().getHours());
|
||||||
|
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStop().getMinutes());
|
||||||
|
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStop().getSeconds());
|
||||||
|
calculationStart.set(Calendar.MILLISECOND, 0);
|
||||||
|
calculationStart.add(Calendar.SECOND, (int) tf.getRepetition());
|
||||||
|
|
||||||
|
int dayDelta = getDayDelta(now, getNextDayIntForExecution(trigger));
|
||||||
|
calculationStart.add(Calendar.DAY_OF_WEEK, dayDelta);
|
||||||
|
}
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
|
||||||
|
return calSchedule;
|
||||||
|
}
|
||||||
|
/*long differenceInSeconds = Math.abs(now.getTimeInMillis() - calculationStart.getTimeInMillis()) / 1000;
|
||||||
|
long nextExecutionMultiplier = Math.floorDiv(differenceInSeconds, tf.getRepetition()) + 1;
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
calSchedule.add(Calendar.SECOND, (int) (nextExecutionMultiplier * tf.getRepetition()));*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calculationStart = (Calendar) now.clone();
|
||||||
|
calculationStart.set(Calendar.HOUR_OF_DAY, tf.getTriggerTimeStart().getHours());
|
||||||
|
calculationStart.set(Calendar.MINUTE, tf.getTriggerTimeStart().getMinutes());
|
||||||
|
calculationStart.set(Calendar.SECOND, tf.getTriggerTimeStart().getSeconds());
|
||||||
|
calculationStart.set(Calendar.MILLISECOND, 0);
|
||||||
|
calSchedule = (Calendar) calculationStart.clone();
|
||||||
|
calSchedule.add(Calendar.SECOND, (int) (tf.getRepetition()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Miscellaneous.compareTimes(calSchedule, now) > 0)
|
||||||
|
calSchedule.add(Calendar.DAY_OF_MONTH, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dayDelta = getDayDelta(now, getNextDayIntForExecution(trigger));
|
||||||
|
calSchedule.add(Calendar.DAY_OF_WEEK, dayDelta);
|
||||||
|
|
||||||
|
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Chose " + Miscellaneous.formatDate(calSchedule.getTime()) + " as next repeated execution time.", 5);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Miscellaneous.logEvent("i", "DateTimeListener", "Trigger " + trigger.toString() + " is not executed repeatedly.", 5);
|
Miscellaneous.logEvent("i", "getNextRepeatedExecutionAfter()", "Trigger " + trigger.toString() + " is not configured to repeat.", 5);
|
||||||
|
|
||||||
return null;
|
return calSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean areWeInTimeFrame(Trigger trigger, Object triggeringObject)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Use format known from Automation
|
||||||
|
* 07:30:00/17:30:00/23456/300 <-- last parameter is optional: repetition in seconds
|
||||||
|
* Also required: inside or outside that interval
|
||||||
|
*/
|
||||||
|
|
||||||
|
Date triggeringTime;
|
||||||
|
// if(triggeringObject instanceof Date)
|
||||||
|
// triggeringTime = (Date)triggeringObject;
|
||||||
|
// else
|
||||||
|
triggeringTime = new Date();
|
||||||
|
|
||||||
|
String timeString = String.valueOf(triggeringTime.getHours()) + ":" + String.valueOf(triggeringTime.getMinutes()) + ":" + String.valueOf(triggeringTime.getSeconds());
|
||||||
|
TimeObject nowTime = TimeObject.valueOf(timeString);
|
||||||
|
Calendar calNow = Calendar.getInstance();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TimeFrame tf = new TimeFrame(trigger.getTriggerParameter2());
|
||||||
|
|
||||||
|
if(tf.getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK)))
|
||||||
|
{
|
||||||
|
if(
|
||||||
|
// Regular case, start time is lower than end time
|
||||||
|
(
|
||||||
|
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
|
||||||
|
&&
|
||||||
|
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0
|
||||||
|
)
|
||||||
|
||
|
||||||
|
// Other case, start time higher than end time, timeframe goes over midnight
|
||||||
|
(
|
||||||
|
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) < 0
|
||||||
|
&&
|
||||||
|
(Miscellaneous.compareTimes(tf.getTriggerTimeStart(), nowTime) >= 0
|
||||||
|
||
|
||||||
|
Miscellaneous.compareTimes(nowTime, tf.getTriggerTimeStop()) > 0)
|
||||||
|
)
|
||||||
|
||
|
||||||
|
// further case: start and end times are identical, meaning a 24h window
|
||||||
|
(
|
||||||
|
Miscellaneous.compareTimes(tf.getTriggerTimeStart(), tf.getTriggerTimeStop()) == 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("e", "Trigger", "There was an error while checking if the time based trigger applies: " + Log.getStackTraceString(e), 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -66,18 +66,6 @@ public class NotificationListener extends NotificationListenerService// implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addUsedPair(RuleNotificationPair pair)
|
|
||||||
{
|
|
||||||
// Add pair only if it's not in the list already.
|
|
||||||
for(RuleNotificationPair usedPair : notificationUsed)
|
|
||||||
{
|
|
||||||
if(usedPair.rule.equals(pair.rule) && usedPair.notification.equals(pair.notification))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationUsed.add(pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate()
|
public void onCreate()
|
||||||
{
|
{
|
||||||
@ -112,6 +100,7 @@ public class NotificationListener extends NotificationListenerService// implemen
|
|||||||
|
|
||||||
synchronized boolean checkNotification(boolean created, StatusBarNotification sbn)
|
synchronized boolean checkNotification(boolean created, StatusBarNotification sbn)
|
||||||
{
|
{
|
||||||
|
//TODO: Merge with functino in Trigger class
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
|
||||||
{
|
{
|
||||||
lastNotification = convertNotificationToSimpleNotification(created, sbn);
|
lastNotification = convertNotificationToSimpleNotification(created, sbn);
|
||||||
|
@ -76,12 +76,12 @@ public class TimeZoneListener extends BroadcastReceiver implements AutomationLis
|
|||||||
if(action.equals(Intent.ACTION_TIMEZONE_CHANGED))
|
if(action.equals(Intent.ACTION_TIMEZONE_CHANGED))
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Device timezone changed. Reloading alarms.", 3);
|
Miscellaneous.logEvent("i", "TimeZoneListener", "Device timezone changed. Reloading alarms.", 3);
|
||||||
DateTimeListener.reloadAlarms();
|
DateTimeListener.setOrResetAlarms();
|
||||||
}
|
}
|
||||||
else if(action.equals(Intent.ACTION_TIME_CHANGED))
|
else if(action.equals(Intent.ACTION_TIME_CHANGED))
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 3);
|
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 3);
|
||||||
DateTimeListener.reloadAlarms();
|
DateTimeListener.setOrResetAlarms();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,21 +88,54 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_margin="10dp" >
|
android:layout_margin="10dp" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvRuleHelpText"
|
android:id="@+id/tvRuleHelpText"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/helpTextRules" />
|
android:text="@string/helpTextRules" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/barBackgroundColor" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvProfileTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/profiles"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_margin="10dp" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvProfileHelpText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/helpTextProfiles" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
|
123
app/src/main/res/layout/activity_manage_trigger_charging.xml
Normal file
123
app/src/main/res/layout/activity_manage_trigger_charging.xml
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_margin="@dimen/default_margin" >
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_span="2"
|
||||||
|
android:textSize="25dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="@dimen/default_margin"
|
||||||
|
android:text="@string/triggerCharging"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/triggerChargingComment" />
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/default_margin"
|
||||||
|
android:stretchColumns="1"
|
||||||
|
android:shrinkColumns="1" >
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_marginTop="@dimen/default_margin">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="@dimen/default_margin"
|
||||||
|
android:text="@string/state" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingOn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/charging" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingOff"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/notCharging" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:background="#aa000000" />
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="@dimen/default_margin"
|
||||||
|
android:text="@string/type" />
|
||||||
|
|
||||||
|
<RadioGroup>
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingTypeAny"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/any" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingTypeAc"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/charging_AC" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingTypeUsb"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/usb" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbChargingTypeWireless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/charging_wireless" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bTriggerChargingSave"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/default_margin"
|
||||||
|
android:text="@string/save" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
@ -120,7 +120,7 @@
|
|||||||
<string name="soundSettings">Ton Einstellungen</string>
|
<string name="soundSettings">Ton Einstellungen</string>
|
||||||
<string name="showHelp">Hilfe</string>
|
<string name="showHelp">Hilfe</string>
|
||||||
<string name="rules">Regeln</string>
|
<string name="rules">Regeln</string>
|
||||||
<string name="helpTextRules">Alle Auslöser sind UND-verknüpft. D.h. die Regel wird nur zutreffen, wenn alle Bedingungen erfüllt sind. Wenn Sie eine ODER-Verknüpfung möchten, müssen Sie eine weitere Regel erstellen.\nDie Begriffe Auslöser und Bedingung werden synonym verwendet. Alle von ihnen sind Bedingungen, aber die letzte, die ihren erforderlichen Wert erfüllt, könnte als Auslöser bezeichnet werden, da sie das letzte Teil des Puzzles ist, um eine Regel auszuführen.</string>
|
<string name="helpTextRules">Alle Auslöser sind UND-verknüpft. D.h. die Regel wird nur zutreffen, wenn alle Bedingungen erfüllt sind. Wenn Sie eine ODER-Verknüpfung möchten, müssen Sie eine weitere Regel erstellen.\nDie Begriffe Auslöser und Bedingung werden synonym verwendet. Alle von ihnen sind Bedingungen, aber die letzte, die ihren erforderlichen Wert erfüllt, könnte als Auslöser bezeichnet werden, da sie das letzte Teil des Puzzles ist, um eine Regel auszuführen.\nWenn Sie bestimmte Werte aus einer Regel speichern und in einer anderen Regel auswerten möchten, schauen Sie sich mal den Auslöser/Aktion Variable an.</string>
|
||||||
<string name="timeframes">Zeiträume</string>
|
<string name="timeframes">Zeiträume</string>
|
||||||
<string name="helpTextTimeFrame">Wenn Sie eine Regel mit einem Zeitraum erstellen, haben Sie zwei Möglichkeiten. Sie können wählen, ob der Auslöser besagt, daß der Zeitraum entweder verlassen ODER betreten wird. In jedem Fall wird die Regel nur einmal ausgelöst. Wenn eine Regel z.B. besagt \"betrete timeframe xyz\" und das Klingeltonprofil in Vibration ändert, bedeutet das NICHT, daß das Gerät hinterher automatisch wieder zum normalen Klingelprofil zurückschaltet. Wenn das erwünscht ist, muß eine weitere Regel mit einem Folgezeitraum erstellen werden.</string>
|
<string name="helpTextTimeFrame">Wenn Sie eine Regel mit einem Zeitraum erstellen, haben Sie zwei Möglichkeiten. Sie können wählen, ob der Auslöser besagt, daß der Zeitraum entweder verlassen ODER betreten wird. In jedem Fall wird die Regel nur einmal ausgelöst. Wenn eine Regel z.B. besagt \"betrete timeframe xyz\" und das Klingeltonprofil in Vibration ändert, bedeutet das NICHT, daß das Gerät hinterher automatisch wieder zum normalen Klingelprofil zurückschaltet. Wenn das erwünscht ist, muß eine weitere Regel mit einem Folgezeitraum erstellen werden.</string>
|
||||||
<string name="helpTextSound">Auf dem Hauptbildschirm können Sie die Funktion Tonänderunugen sperren benutzen, um vorrübergehend regelbasierte Tonänderungen zu deaktivieren. Z.B. könnten Sie in einer Situation oder an einem Ort sein, wo Klingeltöne normalerweise in Ordnung sind, aber dieses eine Mal würde es stören. Die Funktion wird automatisch wieder deaktiviert nachdem die eingestellte Zeit abgelaufen ist. Klicken Sie den + Knopf, um die angezeigte Zeit zur Frist hinzuzufügen. Sobald es aktiv ist, können Sie es mit dem Schalter rechts wieder abschalten (und so regelbasierte Tonänderungen wieder ermöglichen).</string>
|
<string name="helpTextSound">Auf dem Hauptbildschirm können Sie die Funktion Tonänderunugen sperren benutzen, um vorrübergehend regelbasierte Tonänderungen zu deaktivieren. Z.B. könnten Sie in einer Situation oder an einem Ort sein, wo Klingeltöne normalerweise in Ordnung sind, aber dieses eine Mal würde es stören. Die Funktion wird automatisch wieder deaktiviert nachdem die eingestellte Zeit abgelaufen ist. Klicken Sie den + Knopf, um die angezeigte Zeit zur Frist hinzuzufügen. Sobald es aktiv ist, können Sie es mit dem Schalter rechts wieder abschalten (und so regelbasierte Tonänderungen wieder ermöglichen).</string>
|
||||||
@ -848,4 +848,11 @@
|
|||||||
<string name="reoccurringTrue">Ereignis ist wiederkehrend</string>
|
<string name="reoccurringTrue">Ereignis ist wiederkehrend</string>
|
||||||
<string name="reoccurring">wiederkehrend</string>
|
<string name="reoccurring">wiederkehrend</string>
|
||||||
<string name="calendarTriggerExecutionHints">Wenn Ihr Kalender mehrere parallele, überlappende oder direkt aufeinanderfolgende Ereignisse enthält, wird eine Regel so oft ausgeführt, wie es Ereignisse gibt, die den Kriterien der Regel entsprechen. Falls eine Regel mehrere Kalenderauslöser hat und mehrere übereinstimmende Ereignisse parallel vorhanden sind, wird die Regel nur einmal ausgeführt.</string>
|
<string name="calendarTriggerExecutionHints">Wenn Ihr Kalender mehrere parallele, überlappende oder direkt aufeinanderfolgende Ereignisse enthält, wird eine Regel so oft ausgeführt, wie es Ereignisse gibt, die den Kriterien der Regel entsprechen. Falls eine Regel mehrere Kalenderauslöser hat und mehrere übereinstimmende Ereignisse parallel vorhanden sind, wird die Regel nur einmal ausgeführt.</string>
|
||||||
|
<string name="charging_AC">Ladegerät</string>
|
||||||
|
<string name="charging_wireless">drahtlos</string>
|
||||||
|
<string name="charging">laden</string>
|
||||||
|
<string name="notCharging">nicht laden</string>
|
||||||
|
<string name="triggerChargingComment">Der Typ wird nur ausgewertet, wenn das Gerät aufgeladen wird. Wenn \"Nicht laden\" ausgewählt ist, wird es bei jedem vorherigen Ladetyp ausgelöst. Wenn Sie dies auswerten möchten, sollten Sie die Verwendung der Variablen trigger/action in Betracht ziehen.</string>
|
||||||
|
<string name="helpTextProfiles">Ein Profil ist eine Sammlung von Einstellungen für Klingeltöne, Lautstärke und andere audiobezogene Einstellungen, die Sie über Regeln oder manuell anwenden können.\\n\\nEs ist auch möglich, das zuletzt aktivierte Profil als Auslöser abzufragen. Im Normalfall wird nur abgefragt, ob das Profil das zuletzt aktivierte war (unabhängig davon, ob in der Zwischenzeit bestimmte Audioeinstellungen geändert wurden). Sie können aber auch die einzelnen Einstellungen vergleichen lassen.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Es sind keine aktivierten Regeln definiert. Der Dienst wird nicht gestartet.</string>
|
||||||
</resources>
|
</resources>
|
@ -374,7 +374,7 @@
|
|||||||
<string name="com.wireguard.android.permission.CONTROL_TUNNELS">Controlar conexiones de la app Wireguard</string>
|
<string name="com.wireguard.android.permission.CONTROL_TUNNELS">Controlar conexiones de la app Wireguard</string>
|
||||||
<string name="shareConfigAndLogFilesWithDev">Adjuntar configuración y procotolo.</string>
|
<string name="shareConfigAndLogFilesWithDev">Adjuntar configuración y procotolo.</string>
|
||||||
<string name="rootExplanation">Necesita permiso root para esta función. Después encienda la función \"ejecutar regla manualmente\" para presentar el permiso superuser dialogo. Es necesario elegir \"siempre permitir root para esta app\". En caso contrario la regla no puede funcionar en segundo plano.</string>
|
<string name="rootExplanation">Necesita permiso root para esta función. Después encienda la función \"ejecutar regla manualmente\" para presentar el permiso superuser dialogo. Es necesario elegir \"siempre permitir root para esta app\". En caso contrario la regla no puede funcionar en segundo plano.</string>
|
||||||
<string name="helpTextRules">Todas las condiciones están \"Y\"-conectadas. La regla solo va a aplicarse cuando todas las condiciones se aplican. Si quiere \"O\", cree otra regla.\nLos términos desencadenante y condición se utilizan como sinónimos. Todas ellas son condiciones, pero la última en cumplir con su valor requerido podría llamarse disparador porque es la pieza final del rompecabezas para hacer que se ejecute una regla.</string>
|
<string name="helpTextRules">Todas las condiciones están \"Y\"-conectadas. La regla solo va a aplicarse cuando todas las condiciones se aplican. Si quiere \"O\", cree otra regla.\nLos términos desencadenante y condición se utilizan como sinónimos. Todas ellas son condiciones, pero la última en cumplir con su valor requerido podría llamarse disparador porque es la pieza final del rompecabezas para hacer que se ejecute una regla.\nSi desea guardar ciertas variables de una regla y evaluarlas en otra regla, extraiga la variable condición/actión.</string>
|
||||||
<string name="timeBetweenNoiseLevelMeasurementsSummary">Segundos entre dos ensayos de nivel de ruido</string>
|
<string name="timeBetweenNoiseLevelMeasurementsSummary">Segundos entre dos ensayos de nivel de ruido</string>
|
||||||
<string name="timeBetweenNoiseLevelMeasurementsTitle">Segundos entre dos ensayos de nivel de ruido</string>
|
<string name="timeBetweenNoiseLevelMeasurementsTitle">Segundos entre dos ensayos de nivel de ruido</string>
|
||||||
<string name="lengthOfNoiseLevelMeasurementsSummary">Duración en segundos para una prueba de nivel de ruido</string>
|
<string name="lengthOfNoiseLevelMeasurementsSummary">Duración en segundos para una prueba de nivel de ruido</string>
|
||||||
@ -847,4 +847,11 @@
|
|||||||
<string name="reoccurringTrue">El evento se repite</string>
|
<string name="reoccurringTrue">El evento se repite</string>
|
||||||
<string name="reoccurring">Recurrente</string>
|
<string name="reoccurring">Recurrente</string>
|
||||||
<string name="calendarTriggerExecutionHints">Si su calendario contiene varios eventos paralelos, superpuestos o directamente posteriores, una regla se ejecutará tantas veces como eventos coincidan con los criterios de la regla. En caso de que una regla tenga varios activadores de calendario y haya varios eventos coincidentes en paralelo, la regla se ejecutará solo una vez.</string>
|
<string name="calendarTriggerExecutionHints">Si su calendario contiene varios eventos paralelos, superpuestos o directamente posteriores, una regla se ejecutará tantas veces como eventos coincidan con los criterios de la regla. En caso de que una regla tenga varios activadores de calendario y haya varios eventos coincidentes en paralelo, la regla se ejecutará solo una vez.</string>
|
||||||
|
<string name="charging_AC">cargador</string>
|
||||||
|
<string name="charging_wireless">inalámbrico</string>
|
||||||
|
<string name="charging">cargando</string>
|
||||||
|
<string name="notCharging">no cargando</string>
|
||||||
|
<string name="triggerChargingComment">El tipo solo se evaluará si el dispositivo se está cargando. Si se elige no cargar, se disparará en cualquier tipo de carga anterior. Si desea evaluar eso, considere la posibilidad de usar las variables trigger/action.</string>
|
||||||
|
<string name="helpTextProfiles">Un perfil es una colección de ajustes para tonos de llamada, volúmenes y otros ajustes relacionados con el audio que puede aplicar desde reglas o aplicarlo manualmente.\\n\\nTambién es posible consultar el último perfil activado como disparador. En el caso normal, solo consultará si el perfil fue el último activado (independientemente de si se han cambiado configuraciones de audio específicas mientras tanto). Pero también puede comparar los ajustes individuales.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">No se han definido reglas activadas. El servicio no se inicia.</string>
|
||||||
</resources>
|
</resources>
|
@ -120,7 +120,7 @@
|
|||||||
<string name="soundSettings">Réglages audio</string>
|
<string name="soundSettings">Réglages audio</string>
|
||||||
<string name="showHelp">Afficher l’aide</string>
|
<string name="showHelp">Afficher l’aide</string>
|
||||||
<string name="rules">Règles</string>
|
<string name="rules">Règles</string>
|
||||||
<string name="helpTextRules">Tous les déclencheurs d’une règle sont reliés par un lien logique ET, la règle ne s’applique que si tous les déclencheurs sont satisfaits. Pour un lien logique OU, créez une autre règle.\nLes termes déclencheur et condition sont utilisés comme synonymes. Toutes sont des conditions, mais la dernière à atteindre sa valeur requise pourrait être appelée déclencheur car c\'est la dernière pièce du puzzle pour provoquer l\'exécution d\'une règle.</string>
|
<string name="helpTextRules">Tous les déclencheurs d’une règle sont reliés par un lien logique ET, la règle ne s’applique que si tous les déclencheurs sont satisfaits. Pour un lien logique OU, créez une autre règle.\nLes termes déclencheur et condition sont utilisés comme synonymes. Toutes sont des conditions, mais la dernière à atteindre sa valeur requise pourrait être appelée déclencheur car c\'est la dernière pièce du puzzle pour provoquer l\'exécution d\'une règle.\nSi vous souhaitez enregistrer certaines variables d\'une règle et les évaluer dans une autre règle, extrayez le déclencheur/l\'action de la variable.</string>
|
||||||
<string name="timeframes">Délais d’éxécution</string>
|
<string name="timeframes">Délais d’éxécution</string>
|
||||||
<string name="helpTextTimeFrame">Si vous créez une règle avec une période d’éxécution vous avez deux options. Vous pouvez choisir d’éxécuter dans la période OU hors de la période. Quel que soit votre choix l’action ne sera déclenchée qu’une seule fois. Si vous créez une règle avec pour déclencheur \« dans la période xyz \» qui modifie votre profil audio en le passant en mode vibreur cela ne signifie pas que votre téléphone repassera automatiquement en mode sonnerie à la fin de la période. Si vous souhaitez le faire vous devez définir une autre règle avec une autre période.</string>
|
<string name="helpTextTimeFrame">Si vous créez une règle avec une période d’éxécution vous avez deux options. Vous pouvez choisir d’éxécuter dans la période OU hors de la période. Quel que soit votre choix l’action ne sera déclenchée qu’une seule fois. Si vous créez une règle avec pour déclencheur \« dans la période xyz \» qui modifie votre profil audio en le passant en mode vibreur cela ne signifie pas que votre téléphone repassera automatiquement en mode sonnerie à la fin de la période. Si vous souhaitez le faire vous devez définir une autre règle avec une autre période.</string>
|
||||||
<string name="helpTextSound">Sur l’écran principal vous pouvez utiliser le verrouillage des modifications audio pour temporairement ne pas utiliser les règles de changement des paramètres audio. Par exemple vous pouvez êtes dans un lieu où à un moment où les sonneries peuvent être dérangeantes. Cette fonctionnalité se désactivera automatiquement une fois le temps configuré écoulé. Appuyez sur le bouton + 15 min pour ajouter la durée souhaitée. Une fois activé vous pouvez le désactiver en appuyant sur le bouton \« OUI \» (la règle de gestion des paramètres audio sera de nouveau active).</string>
|
<string name="helpTextSound">Sur l’écran principal vous pouvez utiliser le verrouillage des modifications audio pour temporairement ne pas utiliser les règles de changement des paramètres audio. Par exemple vous pouvez êtes dans un lieu où à un moment où les sonneries peuvent être dérangeantes. Cette fonctionnalité se désactivera automatiquement une fois le temps configuré écoulé. Appuyez sur le bouton + 15 min pour ajouter la durée souhaitée. Une fois activé vous pouvez le désactiver en appuyant sur le bouton \« OUI \» (la règle de gestion des paramètres audio sera de nouveau active).</string>
|
||||||
@ -847,4 +847,11 @@
|
|||||||
<string name="reoccurringTrue">l\'événement se reproduit</string>
|
<string name="reoccurringTrue">l\'événement se reproduit</string>
|
||||||
<string name="reoccurring">Récurrents</string>
|
<string name="reoccurring">Récurrents</string>
|
||||||
<string name="calendarTriggerExecutionHints">Si votre calendrier contient plusieurs événements parallèles, qui se chevauchent ou qui se suivent directement, une règle sera exécutée autant de fois qu\'il y a d\'événements correspondant aux critères de la règle. Dans le cas où une règle a plusieurs déclencheurs de calendrier et qu\'il y a plusieurs événements correspondants en parallèle, la règle ne sera exécutée qu\'une seule fois.</string>
|
<string name="calendarTriggerExecutionHints">Si votre calendrier contient plusieurs événements parallèles, qui se chevauchent ou qui se suivent directement, une règle sera exécutée autant de fois qu\'il y a d\'événements correspondant aux critères de la règle. Dans le cas où une règle a plusieurs déclencheurs de calendrier et qu\'il y a plusieurs événements correspondants en parallèle, la règle ne sera exécutée qu\'une seule fois.</string>
|
||||||
|
<string name="charging_AC">chargeur</string>
|
||||||
|
<string name="charging_wireless">sans fil</string>
|
||||||
|
<string name="charging">Charge</string>
|
||||||
|
<string name="notCharging">Ne charge pas</string>
|
||||||
|
<string name="triggerChargingComment">Le type ne sera évalué que si l\'appareil est en charge. Si l\'option Ne pas charger est sélectionnée, elle se déclenchera à n\'importe quel type de charge précédent. Si vous souhaitez évaluer cela, envisagez d\'utiliser les variables déclencheur/action.</string>
|
||||||
|
<string name="helpTextProfiles">Un profil est un ensemble de paramètres pour les sonneries, les volumes et d\'autres paramètres liés à l\'audio que vous pouvez faire appliquer à partir de règles ou appliquer manuellement.\\n\\nIl est également possible d\'interroger le dernier profil activé en tant que déclencheur. Dans le cas normal, il ne demandera que si le profil était le dernier activé (indépendamment si des paramètres audio spécifiques ont été modifiés entre-temps). Mais vous pouvez également comparer les différents paramètres.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Aucune règle activée n\'a été définie. Le service ne démarre pas.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -228,7 +228,7 @@
|
|||||||
<string name="helpTextEnergySaving">Molti produttori di dispositive Android cercano di salvare energia limitando le attività di applicazioni eseguite in secondo piano. Sfortunatamente, questo spesso fa che tali applicazioni non funzionino correttamente e Automation è fra queste. Puoi leggere questa <a href="https://dontkillmyapp.com/">pagina web</a> per scoprire come escludere Automation da queste funzioni di risparmio energetico.</string>
|
<string name="helpTextEnergySaving">Molti produttori di dispositive Android cercano di salvare energia limitando le attività di applicazioni eseguite in secondo piano. Sfortunatamente, questo spesso fa che tali applicazioni non funzionino correttamente e Automation è fra queste. Puoi leggere questa <a href="https://dontkillmyapp.com/">pagina web</a> per scoprire come escludere Automation da queste funzioni di risparmio energetico.</string>
|
||||||
<string name="helpTextPoi">Una posizione è composta da coordinate GPS ed un raggio d\'azione. Dato che il posizionamento realizzato tramite i ripetitori del tuo gestore è piuttosto impreciso (ma veloce e consuma poca batteria), è bene non specificare un raggio troppo piccolo. L\'applicazione suggerisce un raggio minimo quando si crea una nuova posizione.</string>
|
<string name="helpTextPoi">Una posizione è composta da coordinate GPS ed un raggio d\'azione. Dato che il posizionamento realizzato tramite i ripetitori del tuo gestore è piuttosto impreciso (ma veloce e consuma poca batteria), è bene non specificare un raggio troppo piccolo. L\'applicazione suggerisce un raggio minimo quando si crea una nuova posizione.</string>
|
||||||
<string name="helpTextProcessMonitoring">Se si specifica una regola che controlli l\'esecuzione di un processo, Automation eseguirà la verifica ogni x secondi (con x selezionabile nelle impostazioni). Bisogna considerare che un monitoraggio costante provocherebbe un rapido esaurimento della batteria e non esistono notifiche di questo tipo di attività proviste dal sistema operativo.</string>
|
<string name="helpTextProcessMonitoring">Se si specifica una regola che controlli l\'esecuzione di un processo, Automation eseguirà la verifica ogni x secondi (con x selezionabile nelle impostazioni). Bisogna considerare che un monitoraggio costante provocherebbe un rapido esaurimento della batteria e non esistono notifiche di questo tipo di attività proviste dal sistema operativo.</string>
|
||||||
<string name="helpTextRules">Gli eventi di attivazione sono in AND logico. La regola sarà eseguita solo se tutti gli eventi sono soddisfatti. Per l\'OR logico basta creare un\'altra regola.\nI termini trigger e condizione vengono utilizzati come sinonimi. Tutte sono condizioni, ma l\'ultima a soddisfare il valore richiesto potrebbe essere chiamata trigger perché è il pezzo finale del puzzle per causare l\'esecuzione di una regola.</string>
|
<string name="helpTextRules">Gli eventi di attivazione sono in AND logico. La regola sarà eseguita solo se tutti gli eventi sono soddisfatti. Per l\'OR logico basta creare un\'altra regola.\nI termini trigger e condizione vengono utilizzati come sinonimi. Tutte sono condizioni, ma l\'ultima a soddisfare il valore richiesto potrebbe essere chiamata trigger perché è il pezzo finale del puzzle per causare l\'esecuzione di una regola.\nSe si desidera salvare determinate variabili da una regola e valutarle in un\'altra regola, eseguire il checkout del trigger/azione della variabile.</string>
|
||||||
<string name="helpTextSound">Nello schermo principale puoi bloccare temporaneamente i cambi ai suoni per evitare l\'esecuzione di regole che facciano cambi alle attività sonore. Per esempio, potresti essere in una situatione o in un luogo dove normalmente ascoltare il suono di una suoneria è ok, ma in questa occasione bisognerebbe evitarlo. Questa funzione si disattiverà automaticamente non appena sia trascorso il tempo selezionato. Fai Click sul bottone + per raggiungere la quantità di tempo desiderata. Una volta attiva, questa si può disattivare nuovamente usando il pulsante di attivazione (e in questo modo, si riattiveranno le regole basate su cambi sonori).</string>
|
<string name="helpTextSound">Nello schermo principale puoi bloccare temporaneamente i cambi ai suoni per evitare l\'esecuzione di regole che facciano cambi alle attività sonore. Per esempio, potresti essere in una situatione o in un luogo dove normalmente ascoltare il suono di una suoneria è ok, ma in questa occasione bisognerebbe evitarlo. Questa funzione si disattiverà automaticamente non appena sia trascorso il tempo selezionato. Fai Click sul bottone + per raggiungere la quantità di tempo desiderata. Una volta attiva, questa si può disattivare nuovamente usando il pulsante di attivazione (e in questo modo, si riattiveranno le regole basate su cambi sonori).</string>
|
||||||
<string name="helpTextTimeFrame">Se si specifica una regola con un intervallo temporale si hanno due scelte. È possibile scegliere se si desidera attivare la regola all\'interno o all\'esterno dell\'intervallo di tempo. In entrambi i casi l\'azione verrà eseguita una sola volta. Quindi, se si crea una regola che imposta il profilo su vibrazione nell\'intervallo temporale xyz, il telefono, passato allo stato vibrazione, rimarrà definitivamente in tale stato anche dopo lo scadere dell\'intervallo di tempo. Se si desidera che ciò avvenga è necessario specificare un\'altra regola con un altro periodo di tempo.</string>
|
<string name="helpTextTimeFrame">Se si specifica una regola con un intervallo temporale si hanno due scelte. È possibile scegliere se si desidera attivare la regola all\'interno o all\'esterno dell\'intervallo di tempo. In entrambi i casi l\'azione verrà eseguita una sola volta. Quindi, se si crea una regola che imposta il profilo su vibrazione nell\'intervallo temporale xyz, il telefono, passato allo stato vibrazione, rimarrà definitivamente in tale stato anche dopo lo scadere dell\'intervallo di tempo. Se si desidera che ciò avvenga è necessario specificare un\'altra regola con un altro periodo di tempo.</string>
|
||||||
<string name="helpTextToggable">Le regole hanno un segno di spunta chiamato "Reversibile". Ciò significa che, se una regola viene eseguita al verificarsi di un evento e poi quest\'ultimo si verifica una seconda volta, il comando della regola verrà eseguito una ulteriore volta in modalità inversa, se possibile. Attualmente questo avverrà solo in combinazione con etichette NFC. Se le si tocca due volte la regola associata invertirà la situazione attuale. Per esempio una regola “Reversibile” può disattivare il WiFi se attivo e viceversa attivarlo se non attivo.</string>
|
<string name="helpTextToggable">Le regole hanno un segno di spunta chiamato "Reversibile". Ciò significa che, se una regola viene eseguita al verificarsi di un evento e poi quest\'ultimo si verifica una seconda volta, il comando della regola verrà eseguito una ulteriore volta in modalità inversa, se possibile. Attualmente questo avverrà solo in combinazione con etichette NFC. Se le si tocca due volte la regola associata invertirà la situazione attuale. Per esempio una regola “Reversibile” può disattivare il WiFi se attivo e viceversa attivarlo se non attivo.</string>
|
||||||
@ -848,4 +848,11 @@
|
|||||||
<string name="reoccurringTrue">l\'evento si ripete</string>
|
<string name="reoccurringTrue">l\'evento si ripete</string>
|
||||||
<string name="reoccurring">Reoccurring</string>
|
<string name="reoccurring">Reoccurring</string>
|
||||||
<string name="calendarTriggerExecutionHints">Se il calendario contiene più eventi paralleli, sovrapposti o direttamente successivi, una regola verrà eseguita tante volte quanti sono gli eventi che corrispondono ai criteri della regola. Nel caso in cui una regola disponga di più trigger di calendario e siano presenti più eventi corrispondenti in parallelo, la regola verrà eseguita una sola volta.</string>
|
<string name="calendarTriggerExecutionHints">Se il calendario contiene più eventi paralleli, sovrapposti o direttamente successivi, una regola verrà eseguita tante volte quanti sono gli eventi che corrispondono ai criteri della regola. Nel caso in cui una regola disponga di più trigger di calendario e siano presenti più eventi corrispondenti in parallelo, la regola verrà eseguita una sola volta.</string>
|
||||||
|
<string name="charging_AC">caricatore</string>
|
||||||
|
<string name="charging_wireless">wireless</string>
|
||||||
|
<string name="charging">caricamento</string>
|
||||||
|
<string name="notCharging">non in carica</string>
|
||||||
|
<string name="triggerChargingComment">Il tipo verrà valutato solo se il dispositivo è in carica. Se si sceglie di non caricare, si attiverà a qualsiasi tipo di ricarica precedente. Se si desidera valutarlo, prendere in considerazione l\'utilizzo delle variabili trigger/action.</string>
|
||||||
|
<string name="helpTextProfiles">Un profilo è una raccolta di impostazioni per suonerie, volumi e altre impostazioni relative all\'audio che è possibile applicare dalle regole o applicare manualmente.\\n\\nÈ anche possibile eseguire una query per l\'ultimo profilo attivato come trigger. In caso normale, chiederà solo se il profilo è stato l\'ultimo attivato (indipendentemente dal fatto che nel frattempo siano state modificate impostazioni audio specifiche). Ma è anche possibile confrontare le singole impostazioni.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Nessuna regola attivata definita. Il servizio non si avvia.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -118,7 +118,7 @@
|
|||||||
<string name="soundSettings">Geluidsinstellingen</string>
|
<string name="soundSettings">Geluidsinstellingen</string>
|
||||||
<string name="showHelp">Toon help</string>
|
<string name="showHelp">Toon help</string>
|
||||||
<string name="rules">Regels</string>
|
<string name="rules">Regels</string>
|
||||||
<string name="helpTextRules">Alle triggers in een regel zijn EN-verbonden (AND). De regel zal alleen worden toegepast als aan alle triggers is voldaan. Als je OR wilt, maak dan een andere regel.\nDe termen trigger en condition worden als synoniem gebruikt. Het zijn allemaal voorwaarden, maar de laatste die aan de vereiste waarde voldoet, kan trigger worden genoemd omdat het het laatste stukje van de puzzel is om een regel uit te voeren.</string>
|
<string name="helpTextRules">Alle triggers in een regel zijn EN-verbonden (AND). De regel zal alleen worden toegepast als aan alle triggers is voldaan. Als je OR wilt, maak dan een andere regel.\nDe termen trigger en condition worden als synoniem gebruikt. Het zijn allemaal voorwaarden, maar de laatste die aan de vereiste waarde voldoet, kan trigger worden genoemd omdat het het laatste stukje van de puzzel is om een regel uit te voeren.\nAls u bepaalde variabelen uit een regel wilt opslaan en deze in een andere regel wilt evalueren, bekijkt u de variabeletrigger/actie.</string>
|
||||||
<string name="timeframes">Tijdsbestek</string>
|
<string name="timeframes">Tijdsbestek</string>
|
||||||
<string name="helpTextTimeFrame">Als je een regel opgeeft met een tijdsbestek heb je twee keuzes. Je kunt kiezen tussen het binnengaan OF het verlaten van een tijdframe. In beide gevallen wordt een regel slechts eenmaal getriggerd. Dus als je een regel maakt met als trigger "ingaan tijdvak xyz" en je laat je geluidsprofiel veranderen in trillen dan betekent dat niet dat de telefoon automatisch gaat rinkelen als het tijdvak voorbij is. Als je dat wilt moet je een andere regel specificeren met een ander tijdsbestek.</string>
|
<string name="helpTextTimeFrame">Als je een regel opgeeft met een tijdsbestek heb je twee keuzes. Je kunt kiezen tussen het binnengaan OF het verlaten van een tijdframe. In beide gevallen wordt een regel slechts eenmaal getriggerd. Dus als je een regel maakt met als trigger "ingaan tijdvak xyz" en je laat je geluidsprofiel veranderen in trillen dan betekent dat niet dat de telefoon automatisch gaat rinkelen als het tijdvak voorbij is. Als je dat wilt moet je een andere regel specificeren met een ander tijdsbestek.</string>
|
||||||
<string name="helpTextSound">Op het hoofdscherm kunt u vergrendelingsgeluiden gebruiken om op regels gebaseerde geluidsveranderingen tijdelijk te vermijden. U kunt bijvoorbeeld in een situatie of plaats zijn waar ringtones normaal gesproken ok zijn, maar deze ene keer zou het storend zijn. De functie zal automatisch worden uitgeschakeld zodra de ingestelde tijd is verstreken. Klik op de + knop om de ingestelde tijd toe te voegen. Zodra het actief is kunt u het weer deactiveren met de toggle knop (en op die manier op regels gebaseerde geluidsveranderingen weer inschakelen).</string>
|
<string name="helpTextSound">Op het hoofdscherm kunt u vergrendelingsgeluiden gebruiken om op regels gebaseerde geluidsveranderingen tijdelijk te vermijden. U kunt bijvoorbeeld in een situatie of plaats zijn waar ringtones normaal gesproken ok zijn, maar deze ene keer zou het storend zijn. De functie zal automatisch worden uitgeschakeld zodra de ingestelde tijd is verstreken. Klik op de + knop om de ingestelde tijd toe te voegen. Zodra het actief is kunt u het weer deactiveren met de toggle knop (en op die manier op regels gebaseerde geluidsveranderingen weer inschakelen).</string>
|
||||||
@ -846,5 +846,12 @@
|
|||||||
<string name="reoccurringTrue">gebeurtenis zich opnieuw voordoet</string>
|
<string name="reoccurringTrue">gebeurtenis zich opnieuw voordoet</string>
|
||||||
<string name="reoccurring">Terugkerende</string>
|
<string name="reoccurring">Terugkerende</string>
|
||||||
<string name="calendarTriggerExecutionHints">Als uw agenda meerdere parallelle, overlappende of direct volgende gebeurtenissen bevat, wordt een regel net zo vaak uitgevoerd als er afspraken zijn die voldoen aan de criteria van de regel. Als een regel meerdere agendatriggers heeft en er meerdere overeenkomende gebeurtenissen parallel zijn, wordt de regel slechts één keer uitgevoerd.</string>
|
<string name="calendarTriggerExecutionHints">Als uw agenda meerdere parallelle, overlappende of direct volgende gebeurtenissen bevat, wordt een regel net zo vaak uitgevoerd als er afspraken zijn die voldoen aan de criteria van de regel. Als een regel meerdere agendatriggers heeft en er meerdere overeenkomende gebeurtenissen parallel zijn, wordt de regel slechts één keer uitgevoerd.</string>
|
||||||
|
<string name="charging_AC">lader</string>
|
||||||
|
<string name="charging_wireless">draadloos</string>
|
||||||
|
<string name="charging">Opladen</string>
|
||||||
|
<string name="notCharging">laadt niet op</string>
|
||||||
|
<string name="triggerChargingComment">Het type wordt alleen geëvalueerd als het apparaat wordt opgeladen. Als er niet wordt gekozen voor opladen, wordt het geactiveerd bij elk eerder oplaadtype. Als je dat wilt evalueren, overweeg dan om de variabelen trigger/actie te gebruiken.</string>
|
||||||
|
<string name="helpTextProfiles">Een profiel is een verzameling instellingen voor beltonen, volumes en andere audiogerelateerde instellingen die u kunt laten toepassen vanuit regels of handmatig kunt toepassen.\\n\\nHet is ook mogelijk om het laatst geactiveerde profiel als trigger op te vragen. In het normale geval zal het alleen opvragen of het profiel het laatst geactiveerde profiel was (ongeacht of specifieke audio-instellingen in de tussentijd zijn gewijzigd). Maar u kunt ook de individuele instellingen laten vergelijken.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Er zijn geen geactiveerde regels gedefinieerd. De service wordt niet gestart.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
<string name="soundSettings">Ustawienia dźwięku</string>
|
<string name="soundSettings">Ustawienia dźwięku</string>
|
||||||
<string name="showHelp">Pokaż pomoc</string>
|
<string name="showHelp">Pokaż pomoc</string>
|
||||||
<string name="rules">Reguły</string>
|
<string name="rules">Reguły</string>
|
||||||
<string name="helpTextRules">Wszystkie wyzwalacze w regule są połączone operatorem AND. Reguła zostanie zastosowana tylko wtedy, gdy zostaną spełnione wszystkie warunki wyzwalające. Jeśli chcesz LUB, utwórz inną regułę.\nWyzwalacz i warunek są używane zamiennie. Wszystkie z nich są warunkami, ale ostatni, który spełnia wymaganą wartość, można nazwać wyzwalaczem, ponieważ jest to ostatni element układanki, który powoduje wykonanie reguły.</string>
|
<string name="helpTextRules">Wszystkie wyzwalacze w regule są połączone operatorem AND. Reguła zostanie zastosowana tylko wtedy, gdy zostaną spełnione wszystkie warunki wyzwalające. Jeśli chcesz LUB, utwórz inną regułę.\nWyzwalacz i warunek są używane zamiennie. Wszystkie z nich są warunkami, ale ostatni, który spełnia wymaganą wartość, można nazwać wyzwalaczem, ponieważ jest to ostatni element układanki, który powoduje wykonanie reguły.\nJeśli chcesz zapisać pewne zmienne z reguły i ocenić je w innej regule, sprawdź wyzwalacz/akcję zmiennej.</string>
|
||||||
<string name="timeframes">Ramy czasowe</string>
|
<string name="timeframes">Ramy czasowe</string>
|
||||||
<string name="helpTextTimeFrame">Jeśli określisz regułę z przedziałem czasowym, masz dwie możliwości. Możesz wybrać między wprowadzeniem LUB opuszczeniem przedziału czasowego. Tak czy inaczej reguła jest uruchamiana tylko raz. Więc jeśli utworzysz regułę, która jako wyzwalacz ma „wprowadzanie przedziału czasowego xyz” i pozwolisz jej zmienić profil dźwiękowy na wibracje, nie oznacza to, że telefon automatycznie zadzwoni, gdy przedział czasowy się skończy. Jeśli chcesz, musisz określić inną regułę z innym przedziałem czasowym.</string>
|
<string name="helpTextTimeFrame">Jeśli określisz regułę z przedziałem czasowym, masz dwie możliwości. Możesz wybrać między wprowadzeniem LUB opuszczeniem przedziału czasowego. Tak czy inaczej reguła jest uruchamiana tylko raz. Więc jeśli utworzysz regułę, która jako wyzwalacz ma „wprowadzanie przedziału czasowego xyz” i pozwolisz jej zmienić profil dźwiękowy na wibracje, nie oznacza to, że telefon automatycznie zadzwoni, gdy przedział czasowy się skończy. Jeśli chcesz, musisz określić inną regułę z innym przedziałem czasowym.</string>
|
||||||
<string name="helpTextSound">On the main screen you can use lock sound changes to temporarily avoid rule based sound changes. E.g. you may be in a situation or place where usually ringtones are ok, but this one time it would be disturbing. The feature will automatically deactivate once the configured time has elapsed. Click the + button to add the given amount of time. Once it is active you may deactivate it again using the toggle button (and that way enable rule based sound changes again).</string>
|
<string name="helpTextSound">On the main screen you can use lock sound changes to temporarily avoid rule based sound changes. E.g. you may be in a situation or place where usually ringtones are ok, but this one time it would be disturbing. The feature will automatically deactivate once the configured time has elapsed. Click the + button to add the given amount of time. Once it is active you may deactivate it again using the toggle button (and that way enable rule based sound changes again).</string>
|
||||||
@ -945,4 +945,11 @@
|
|||||||
<string name="reoccurringTrue">zdarzenie powtarza się</string>
|
<string name="reoccurringTrue">zdarzenie powtarza się</string>
|
||||||
<string name="reoccurring">Cyklicznych</string>
|
<string name="reoccurring">Cyklicznych</string>
|
||||||
<string name="calendarTriggerExecutionHints">Jeśli Twój kalendarz zawiera wiele równoległych, nakładających się na siebie lub bezpośrednio następujących wydarzeń, reguła zostanie wykonana tyle razy, ile jest wydarzeń spełniających kryteria reguły. Jeśli reguła ma wiele wyzwalaczy kalendarza i równolegle występuje wiele pasujących zdarzeń, reguła zostanie wykonana tylko raz.</string>
|
<string name="calendarTriggerExecutionHints">Jeśli Twój kalendarz zawiera wiele równoległych, nakładających się na siebie lub bezpośrednio następujących wydarzeń, reguła zostanie wykonana tyle razy, ile jest wydarzeń spełniających kryteria reguły. Jeśli reguła ma wiele wyzwalaczy kalendarza i równolegle występuje wiele pasujących zdarzeń, reguła zostanie wykonana tylko raz.</string>
|
||||||
|
<string name="charging_AC">Ładowarka</string>
|
||||||
|
<string name="charging_wireless">bezprzewodowy</string>
|
||||||
|
<string name="charging">Ładowania</string>
|
||||||
|
<string name="notCharging">Nie ładuje się</string>
|
||||||
|
<string name="triggerChargingComment">Typ zostanie oceniony tylko wtedy, gdy urządzenie się ładuje. Jeśli nie zostanie wybrane ładowanie, zostanie uruchomione przy dowolnym poprzednim typie ładowania. Jeśli chcesz to ocenić, rozważ użycie zmiennych trigger/action.</string>
|
||||||
|
<string name="helpTextProfiles">Profil jest zbiorem ustawień dzwonków, głośności i innych ustawień związanych z dźwiękiem, które można zastosować z reguł lub zastosować ręcznie.\\n\\nMożliwe jest również zapytanie o ostatnio aktywowany profil jako wyzwalacz. W normalnym przypadku zapyta tylko, czy profil był ostatnio aktywowany (niezależnie od tego, czy określone ustawienia dźwięku zostały zmienione w międzyczasie). Ale możesz także porównać poszczególne ustawienia.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Nie zdefiniowano aktywowanych reguł. Usługa nie uruchamia się.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
<string name="soundSettings">Настройки звука</string>
|
<string name="soundSettings">Настройки звука</string>
|
||||||
<string name="showHelp">Показать справку</string>
|
<string name="showHelp">Показать справку</string>
|
||||||
<string name="rules">Правила</string>
|
<string name="rules">Правила</string>
|
||||||
<string name="helpTextRules">Все триггеры в правиле связаны логикой И. Правило будет применяться только в том случае, если будут выполнены все триггеры. Если вы хотите логику ИЛИ, создайте другое правило.\nТермины триггер и условие используются как синонимы. Все они являются условиями, но последний, отвечающий требуемому значению, может быть назван триггером, потому что это последняя часть паззла, которая вызывает выполнение правила.</string>
|
<string name="helpTextRules">Все триггеры в правиле связаны логикой И. Правило будет применяться только в том случае, если будут выполнены все триггеры. Если вы хотите логику ИЛИ, создайте другое правило.\nТермины триггер и условие используются как синонимы. Все они являются условиями, но последний, отвечающий требуемому значению, может быть назван триггером, потому что это последняя часть паззла, которая вызывает выполнение правила.\nЕсли вы хотите сохранить определенные переменные из правила и оценить их в другом правиле, извлеките переменную trigger/action.</string>
|
||||||
<string name="timeframes">Временные интервалы</string>
|
<string name="timeframes">Временные интервалы</string>
|
||||||
<string name="helpTextTimeFrame">Если вы указываете правило с временными интервалами, у вас есть два варианта. Вы можете выбрать между началом ИЛИ окончанием временного интервала. Правило срабатывает только один раз. Поэтому, если вы создадите правило с "начало временного интервала" в качестве триггера и позволите ему изменить ваш звуковой профиль на вибрацию, это не означает, что телефон автоматически перейдет в обычный режим, когда временной интервал закончится. Если вам это необходимо,создайте другое правило с другим временным интервалом.</string>
|
<string name="helpTextTimeFrame">Если вы указываете правило с временными интервалами, у вас есть два варианта. Вы можете выбрать между началом ИЛИ окончанием временного интервала. Правило срабатывает только один раз. Поэтому, если вы создадите правило с "начало временного интервала" в качестве триггера и позволите ему изменить ваш звуковой профиль на вибрацию, это не означает, что телефон автоматически перейдет в обычный режим, когда временной интервал закончится. Если вам это необходимо,создайте другое правило с другим временным интервалом.</string>
|
||||||
<string name="helpTextSound">На главном экране есть возможность заблокировать изменение уровня громкости вызова сконфигурированными правилами, например, вы можете быть в ситуации или месте, где необходим обычный режим звука, но в настоящее время его использовать нельзя. Эта функция автоматически отключится по истечении заданного времени. Нажмите кнопку +, чтобы задать необходимый период времени. После включения, вы можете вручную выключить его с помощью кнопки переключения (и таким образом снова включить изменения громкости звука).</string>
|
<string name="helpTextSound">На главном экране есть возможность заблокировать изменение уровня громкости вызова сконфигурированными правилами, например, вы можете быть в ситуации или месте, где необходим обычный режим звука, но в настоящее время его использовать нельзя. Эта функция автоматически отключится по истечении заданного времени. Нажмите кнопку +, чтобы задать необходимый период времени. После включения, вы можете вручную выключить его с помощью кнопки переключения (и таким образом снова включить изменения громкости звука).</string>
|
||||||
@ -905,4 +905,11 @@
|
|||||||
<string name="reoccurringTrue">Событие повторяется</string>
|
<string name="reoccurringTrue">Событие повторяется</string>
|
||||||
<string name="reoccurring">Повторяющиеся</string>
|
<string name="reoccurring">Повторяющиеся</string>
|
||||||
<string name="calendarTriggerExecutionHints">Если календарь содержит несколько параллельных, перекрывающихся или непосредственно следующих событий, правило будет выполняться столько раз, сколько событий соответствует критериям правила. В случае, если правило имеет несколько календарных триггеров и параллельно существует несколько совпадающих событий, то правило будет выполнено только один раз.</string>
|
<string name="calendarTriggerExecutionHints">Если календарь содержит несколько параллельных, перекрывающихся или непосредственно следующих событий, правило будет выполняться столько раз, сколько событий соответствует критериям правила. В случае, если правило имеет несколько календарных триггеров и параллельно существует несколько совпадающих событий, то правило будет выполнено только один раз.</string>
|
||||||
|
<string name="charging_AC">обвинитель</string>
|
||||||
|
<string name="charging_wireless">беспроволочный</string>
|
||||||
|
<string name="charging">зарядка</string>
|
||||||
|
<string name="notCharging">не заряжается</string>
|
||||||
|
<string name="triggerChargingComment">Тип будет оцениваться только в том случае, если устройство заряжается. Если зарядка не выбрана, он будет срабатывать при любом предыдущем типе зарядки. Если вы хотите это оценить, подумайте об использовании переменных trigger/action.</string>
|
||||||
|
<string name="helpTextProfiles">Профиль — это набор настроек рингтонов, громкости и других настроек, связанных со звуком, которые можно применить из правил или вручную.\\n\\nТакже в качестве триггера можно запросить последний активированный профиль. В обычном случае он будет запрашивать только то, был ли профиль последним активированным (независимо от того, были ли за это время изменены определенные настройки звука). Но вы также можете сравнить отдельные настройки.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">Активированные правила не определены. Служба не запускается.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
<string name="soundSettings">声音设置</string>
|
<string name="soundSettings">声音设置</string>
|
||||||
<string name="showHelp">显示帮助</string>
|
<string name="showHelp">显示帮助</string>
|
||||||
<string name="rules">规则</string>
|
<string name="rules">规则</string>
|
||||||
<string name="helpTextRules">规则中的所有触发器都是用“与”连接的。规则仅在满足所有触发器时才应用。如果您想要“或”,请创建另一个规则。\n触发器和条件是作为同义词使用的。所有的触发器都是条件,而最后一个满足其要求值的条件可以称为触发器,因为它是导致规则执行的“最后一块拼图”。</string>
|
<string name="helpTextRules">规则中的所有触发器都是用“与”连接的。规则仅在满足所有触发器时才应用。如果您想要“或”,请创建另一个规则。\n触发器和条件是作为同义词使用的。所有的触发器都是条件,而最后一个满足其要求值的条件可以称为触发器,因为它是导致规则执行的“最后一块拼图”。\n如果要保存规则中的某些变量并在另一个规则中评估它们,请查看变量触发器/操作。</string>
|
||||||
<string name="timeframes">时间范围</string>
|
<string name="timeframes">时间范围</string>
|
||||||
<string name="helpTextTimeFrame">指定时间范围规则时有两种选择。您可以选择进入或离开时间范围。无论哪种方式,规则都只会触发一次。因此,如果您创建一个使用触发器“进入时间范围 XYZ”的规则,让它将响铃模式更改为振动,这并不意味着手机会在时间范围结束时自动更改为响铃。如果想要的话,您需要指定另一个规则,使用另一个时间范围。</string>
|
<string name="helpTextTimeFrame">指定时间范围规则时有两种选择。您可以选择进入或离开时间范围。无论哪种方式,规则都只会触发一次。因此,如果您创建一个使用触发器“进入时间范围 XYZ”的规则,让它将响铃模式更改为振动,这并不意味着手机会在时间范围结束时自动更改为响铃。如果想要的话,您需要指定另一个规则,使用另一个时间范围。</string>
|
||||||
<string name="helpTextSound">在主屏幕上,您可以使用“锁定声音更改”来暂时禁用基于规则的声音更改。例如,您可能在通常允许响铃的情况或地点,但这一次响铃会打扰。一旦配置的时间过去,此功能将自动停用。点击 + 按钮以添加给定的时间。当此功能启用时,您可以使用切换按钮将其停用(即重新启用基于规则的声音更改)。</string>
|
<string name="helpTextSound">在主屏幕上,您可以使用“锁定声音更改”来暂时禁用基于规则的声音更改。例如,您可能在通常允许响铃的情况或地点,但这一次响铃会打扰。一旦配置的时间过去,此功能将自动停用。点击 + 按钮以添加给定的时间。当此功能启用时,您可以使用切换按钮将其停用(即重新启用基于规则的声音更改)。</string>
|
||||||
@ -846,4 +846,11 @@
|
|||||||
<string name="reoccurringTrue">事件再次发生</string>
|
<string name="reoccurringTrue">事件再次发生</string>
|
||||||
<string name="reoccurring">重复发生</string>
|
<string name="reoccurring">重复发生</string>
|
||||||
<string name="calendarTriggerExecutionHints">如果您的日历包含多个平行、重叠或直接跟随的事件,则规则的执行次数将与规则条件匹配的事件次数相同。如果规则具有多个日历触发器,并且并行有多个匹配事件,则该规则将仅执行一次。</string>
|
<string name="calendarTriggerExecutionHints">如果您的日历包含多个平行、重叠或直接跟随的事件,则规则的执行次数将与规则条件匹配的事件次数相同。如果规则具有多个日历触发器,并且并行有多个匹配事件,则该规则将仅执行一次。</string>
|
||||||
|
<string name="charging_AC">充电器</string>
|
||||||
|
<string name="charging_wireless">无线电</string>
|
||||||
|
<string name="charging">充电</string>
|
||||||
|
<string name="notCharging">不充电</string>
|
||||||
|
<string name="triggerChargingComment">仅当设备正在充电时,才会评估类型。如果未选择充电,它将以任何以前的充电类型点火。如果要对此进行评估,请考虑使用变量 trigger/action。</string>
|
||||||
|
<string name="helpTextProfiles">配置文件是铃声、音量和其他音频相关设置的集合,您可以从规则中应用这些设置,也可以手动应用。\\n\\n还可以查询上次激活的配置文件作为触发器。在正常情况下,它只会查询配置文件是否是上次激活的配置文件(无论在此期间是否更改了特定的音频设置)。但您也可以比较各个设置。</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">未定义已激活的规则。服务无法启动。</string>
|
||||||
</resources>
|
</resources>
|
@ -12,6 +12,7 @@
|
|||||||
<string name="pleaseSpecifiyTrigger">Please specify at least one trigger.</string>
|
<string name="pleaseSpecifiyTrigger">Please specify at least one trigger.</string>
|
||||||
<string name="pleaseSpecifiyAction">Please specify at least one action.</string>
|
<string name="pleaseSpecifiyAction">Please specify at least one action.</string>
|
||||||
<string name="serviceWontStart">No rules defined. Service won\'t start.</string>
|
<string name="serviceWontStart">No rules defined. Service won\'t start.</string>
|
||||||
|
<string name="serviceWontStartNoActivatedRules">No activated rules defined. Service won\'t start.</string>
|
||||||
<string name="serviceStarted">Automation Service started.</string>
|
<string name="serviceStarted">Automation Service started.</string>
|
||||||
<string name="version">Version %1$s.</string>
|
<string name="version">Version %1$s.</string>
|
||||||
<string name="logServiceStarting" translatable="false">Starting service.</string>
|
<string name="logServiceStarting" translatable="false">Starting service.</string>
|
||||||
@ -125,7 +126,7 @@
|
|||||||
<string name="soundSettings">Sound settings</string>
|
<string name="soundSettings">Sound settings</string>
|
||||||
<string name="showHelp">Show help</string>
|
<string name="showHelp">Show help</string>
|
||||||
<string name="rules">Rules</string>
|
<string name="rules">Rules</string>
|
||||||
<string name="helpTextRules">All triggers in a rule are AND-connected. The rule will only apply if all triggers are met. If you want OR, create another rule.\nThe terms trigger and condition are being used synonymously. All of them are conditions, but the last one to meet its required value could be called trigger because it is the final piece of the puzzle to cause a rule to be executed.</string>
|
<string name="helpTextRules">All triggers in a rule are AND-connected. The rule will only apply if all triggers are met. If you want OR, create another rule.\nThe terms trigger and condition are being used synonymously. All of them are conditions, but the last one to meet its required value could be called trigger because it is the final piece of the puzzle to cause a rule to be executed.\nIf you\'d like to save certain variables from a rule and evaluate them in another rule, checkout the variable trigger/action.</string>
|
||||||
<string name="timeframes">TimeFrames</string>
|
<string name="timeframes">TimeFrames</string>
|
||||||
<string name="helpTextTimeFrame">If you specify a rule with a timeframe you have two choices. You can choose between entering OR leaving a timeframe. Either way a rule is triggered only once. So if you create a rule that has \"entering timeframe xyz\" as trigger and let it change your sound profile to vibrate that does not mean that the phone will automatically go to ring if the timeframe is over. If you want that you need to specify another rule with another timeframe.</string>
|
<string name="helpTextTimeFrame">If you specify a rule with a timeframe you have two choices. You can choose between entering OR leaving a timeframe. Either way a rule is triggered only once. So if you create a rule that has \"entering timeframe xyz\" as trigger and let it change your sound profile to vibrate that does not mean that the phone will automatically go to ring if the timeframe is over. If you want that you need to specify another rule with another timeframe.</string>
|
||||||
<string name="helpTextSound">On the main screen you can use lock sound changes to temporarily avoid rule based sound changes. E.g. you may be in a situation or place where usually ringtones are ok, but this one time it would be disturbing. The feature will automatically deactivate once the configured time has elapsed. Click the + button to add the given amount of time. Once it is active you may deactivate it again using the toggle button (and that way enable rule based sound changes again).</string>
|
<string name="helpTextSound">On the main screen you can use lock sound changes to temporarily avoid rule based sound changes. E.g. you may be in a situation or place where usually ringtones are ok, but this one time it would be disturbing. The feature will automatically deactivate once the configured time has elapsed. Click the + button to add the given amount of time. Once it is active you may deactivate it again using the toggle button (and that way enable rule based sound changes again).</string>
|
||||||
@ -940,4 +941,10 @@
|
|||||||
<string name="reoccurringTrue">event is reoccurring</string>
|
<string name="reoccurringTrue">event is reoccurring</string>
|
||||||
<string name="reoccurring">reoccurring</string>
|
<string name="reoccurring">reoccurring</string>
|
||||||
<string name="calendarTriggerExecutionHints">If your calendar holds multiple parallel, overlapping or directly following events, a rule will get executed as many times as there are events matching the rule\'s criteria. In case a rule has multiple calendar triggers and there are multiple matching events in parallel, then the rule will get executed only once.</string>
|
<string name="calendarTriggerExecutionHints">If your calendar holds multiple parallel, overlapping or directly following events, a rule will get executed as many times as there are events matching the rule\'s criteria. In case a rule has multiple calendar triggers and there are multiple matching events in parallel, then the rule will get executed only once.</string>
|
||||||
|
<string name="charging_AC">AC</string>
|
||||||
|
<string name="charging_wireless">wireless</string>
|
||||||
|
<string name="charging">charging</string>
|
||||||
|
<string name="notCharging">not charging</string>
|
||||||
|
<string name="triggerChargingComment">The type will only be evaluated if the device is charging. If not charging is chosen, it will fire at any previous charging type. If you want to evaluate that, consider using the variables trigger/action.</string>
|
||||||
|
<string name="helpTextProfiles">A profile is a collection of settings for ringtones, volumes and other audio related settings that you can have applied from rules or apply it manually.\n\nIt is also possible to query for the last activated profile as a trigger. In the normal case it will only query if the profile was the last activated one (regardless if specific audio settings have been changed in the meantime). But you can also have the individual settings compared.</string>
|
||||||
</resources>
|
</resources>
|
12
fastlane/metadata/android/de-DE/changelogs/139.txt
Normal file
12
fastlane/metadata/android/de-DE/changelogs/139.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
* Behoben: Overlay-Berechtigung zum Starten einer anderen Programmaktion nur erforderlich, wenn startByActivity() ausgewählt ist
|
||||||
|
* Behoben: Broadcast-Receiver-Trigger löste nichts aus, stürzte aber ab * Behoben: Fehler in Android 14 (nicht in Automation!!) erforderte eine Änderung beim Wählen von MMI-Codes, die ein #-Zeichen enthalten.
|
||||||
|
* Behoben: Speicherberechtigung wurde möglicherweise als nicht erteilt angezeigt, auch wenn sie
|
||||||
|
* Behoben: Ein sehr alter Bugfix wurde auch auf F-Droid- und Google-Play-Editionen angewendet, die irrtümlicherweise nur in der APK-Edition implementiert waren (TimeFrame-Trigger mit Wiederholungen)
|
||||||
|
* Behoben: Seltener Absturz beim Starten des Dienstes
|
||||||
|
* Behoben: Kompensiert für Android-Änderungen, zeitbasierte Trigger sind nun wieder präzise
|
||||||
|
* Hinzugefügt: neue Aktion -> Screenshot machen * Hinzugefügt: Der Ortungsdienst (GPS) kann zwischen den Zuständen umgeschaltet werden, wenn WRITE_SECURE_SETTINGS von einem Computer aus erteilt wurde
|
||||||
|
* Hinzugefügt: triggerUrl-Aktion kann jetzt mit POST und Parametern verwendet werden
|
||||||
|
* Hinzugefügt: Das Ergebnis der triggerUrl-Aktion wird jetzt in einer Variablen gespeichert, wenn Sie es überprüfen möchten
|
||||||
|
* Hinzugefügt: Neuer Auslöser: Kalenderereignisse
|
||||||
|
* Hinzugefügt: Das Ergebnis der runExecutable-Aktion wird jetzt in einer Variablen gespeichert, wenn Sie es überprüfen möchten
|
||||||
|
* Hinzugefügt: Ladeauslöser kann nun zwischen Typen unterscheiden (AC, USB, kabellos)
|
1
fastlane/metadata/android/de-DE/changelogs/141.txt
Normal file
1
fastlane/metadata/android/de-DE/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Kalendar Funktion aus Google Version entfernt
|
3
fastlane/metadata/android/de-DE/changelogs/142.txt
Normal file
3
fastlane/metadata/android/de-DE/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Behoben: Kalender Auslöser wird jetzt in Play Version verborgen
|
||||||
|
* Behoben: Parameter wurde beim Starten anderer Apps nicht korrekt übergeben
|
||||||
|
* Behoben: Absturz beim Verlassen der Einstellungen
|
1
fastlane/metadata/android/en-US/changelogs/137.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/137.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Fixed: Corrected multiple code points that caused crashes when targetApk > 31 (affected only Google Play version)
|
@ -10,4 +10,5 @@
|
|||||||
* Added: triggerUrl action can now be used with POST and parameters
|
* Added: triggerUrl action can now be used with POST and parameters
|
||||||
* Added: Result of triggerUrl action is now stored in a variable if you wish to check it
|
* Added: Result of triggerUrl action is now stored in a variable if you wish to check it
|
||||||
* Added: New trigger: Calendar events
|
* Added: New trigger: Calendar events
|
||||||
* Added: Result of runExecutable action is now stored in a variable if you wish to check it
|
* Added: Result of runExecutable action is now stored in a variable if you wish to check it
|
||||||
|
* Added: Charging trigger can now differentiate between types (AC, USB, wirelessly)
|
1
fastlane/metadata/android/en-US/changelogs/141.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Calendar trigger removed from Google version
|
3
fastlane/metadata/android/en-US/changelogs/142.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Fixed: Calendar trigger hidden from Play version
|
||||||
|
* Fixed: Parameters not correctly supplied when starting other apps
|
||||||
|
* Fixed: Crash when exiting settings while service is running
|
14
fastlane/metadata/android/es-ES/changelogs/139.txt
Normal file
14
fastlane/metadata/android/es-ES/changelogs/139.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
* Corregido: El permiso de superposición para iniciar otra acción del programa solo se requiere si se selecciona startByActivity()
|
||||||
|
* Corregido: El disparador del receptor de transmisión no activaba nada, pero se bloqueaba
|
||||||
|
* Corregido: El error en Android 14 (no en Automatización!!) requería un cambio al marcar códigos MMI que contenían un carácter #.
|
||||||
|
* Corregido: El permiso de almacenamiento podía mostrarse como no concedido incluso si se
|
||||||
|
* Corregido: Se aplicó una corrección de errores muy antigua también a las ediciones F-Droid y Google-Play que por error se había implementado solo en la edición APK (disparador de timeFrame con repeticiones)
|
||||||
|
* Corregido: Raro bloqueo al iniciar el servicio
|
||||||
|
* Corregido: Compensado por los cambios de Android, los disparadores basados en el tiempo ahora son precisos nuevamente
|
||||||
|
* Añadido: nueva acción -> tomar captura de pantalla
|
||||||
|
* Agregado: El servicio de ubicación (GPS) se puede alternar entre estados si WRITE_SECURE_SETTINGS se ha otorgado desde una computadora
|
||||||
|
* Añadido: la acción triggerUrl ahora se puede usar con POST y parámetros
|
||||||
|
* Añadido: El resultado de la acción triggerUrl ahora se almacena en una variable si desea verificarlo
|
||||||
|
* Añadido: Nuevo activador: Eventos de calendario
|
||||||
|
* Añadido: El resultado de la acción runExecutable ahora se almacena en una variable si desea comprobarlo
|
||||||
|
* Añadido: El gatillo de carga ahora puede diferenciar entre tipos (CA, USB, de forma inalámbrica)
|
1
fastlane/metadata/android/es-ES/changelogs/141.txt
Normal file
1
fastlane/metadata/android/es-ES/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Eliminado el activador de calendario de la versión de Google
|
3
fastlane/metadata/android/es-ES/changelogs/142.txt
Normal file
3
fastlane/metadata/android/es-ES/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Corregido: Condición de calendario ahora es oculto en la versión Play
|
||||||
|
* Corregido: Los parámetros no se suministran correctamente al iniciar otras aplicaciones
|
||||||
|
* Corregido: Bloqueo al salir de la configuración mientras el servicio se está ejecutando
|
12
fastlane/metadata/android/fr-FR/changelogs/139.txt
Normal file
12
fastlane/metadata/android/fr-FR/changelogs/139.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
* Corrigé : Autorisation de superposition pour démarrer une autre action de programme requise uniquement si startByActivity() est sélectionnée
|
||||||
|
* Corrigé : Le déclenchement du récepteur de diffusion ne déclenchait rien, mais plantait
|
||||||
|
* Corrigé : Un bug dans Android 14 (pas dans Automation !!) nécessitait un changement lors de la composition des codes MMI contenant un caractère #.
|
||||||
|
* Résolu : L'autorisation de stockage pouvait être affichée comme n'ayant pas été accordée, même si elle l'était
|
||||||
|
* Corrigé : Correction d'un très ancien bug également sur les éditions F-Droid et Google-Play qui n'avait été implémenté par erreur que dans l'édition APK (déclencheur timeFrame avec répétitions)
|
||||||
|
* Corrigé : Crash rare lors du démarrage du service
|
||||||
|
* Corrigé : Corrigé des changements d'Android, les déclencheurs basés sur le temps sont à nouveau précis
|
||||||
|
* Ajouté : nouvelle action > prendre une capture d'écran * Ajouté : Le service de localisation (GPS) peut être basculé entre les états s'WRITE_SECURE_SETTINGS a été accordé à partir d'un ordinateur
|
||||||
|
* Ajout : l'action triggerUrl peut maintenant être utilisée avec l'auto-test de démarrage (POST) et les paramètres
|
||||||
|
* Ajouté : Le résultat de l'action triggerUrl est maintenant stocké dans une variable si vous souhaitez le vérifier
|
||||||
|
* Ajout : Nouveau déclencheur : Événements de calendrier * Ajouté : Le résultat de l'action runExecutable est maintenant stocké dans une variable si vous souhaitez le vérifier
|
||||||
|
* Ajouté : La gâchette de charge peut désormais différencier les types (AC, USB, sans fil)
|
1
fastlane/metadata/android/fr-FR/changelogs/141.txt
Normal file
1
fastlane/metadata/android/fr-FR/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Déclencheur d'agenda supprimé de la version Google
|
3
fastlane/metadata/android/fr-FR/changelogs/142.txt
Normal file
3
fastlane/metadata/android/fr-FR/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Correction : Déclencheur de calendrier caché dans la version Play
|
||||||
|
* Correction : Les paramètres n'étaient pas correctement fournis lors du démarrage d'autres applications
|
||||||
|
* Correction : Plantage lors de la fermeture des paramètres pendant l'exécution du service
|
14
fastlane/metadata/android/it-IT/changelogs/139.txt
Normal file
14
fastlane/metadata/android/it-IT/changelogs/139.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
* Risolto: l'autorizzazione di sovrapposizione per l'avvio di un'altra azione del programma è richiesta solo se è selezionato startByActivity()
|
||||||
|
* Risolto: il trigger del ricevitore di trasmissione non attivava nulla, ma si bloccava
|
||||||
|
* Risolto: un bug in Android 14 (non in Automazione!!) richiedeva una modifica durante la composizione dei codici MMI contenenti un carattere #.
|
||||||
|
* Risolto: l'autorizzazione di archiviazione poteva essere visualizzata come non concessa anche se lo era
|
||||||
|
* Risolto: Applicato un bug molto vecchio anche alle edizioni F-Droid e Google-Play che per errore era stato implementato solo nell'edizione APK (trigger timeFrame con ripetizioni)
|
||||||
|
* Risolto: raro crash durante l'avvio del servizio
|
||||||
|
* Risolto: compensato per le modifiche di Android, i trigger basati sul tempo ora sono di nuovo precisi
|
||||||
|
* Aggiunto: nuova azione -> fai screenshot
|
||||||
|
* Aggiunto: il servizio di localizzazione (GPS) può essere commutato tra gli stati se WRITE_SECURE_SETTINGS è stato concesso da un computer
|
||||||
|
* Aggiunto: l'azione triggerUrl può ora essere utilizzata con POST e parametri
|
||||||
|
* Aggiunto: il risultato dell'azione triggerUrl è ora memorizzato in una variabile se si desidera controllarlo
|
||||||
|
* Aggiunto: Nuovo trigger: Eventi del calendario
|
||||||
|
* Aggiunto: il risultato dell'azione runExecutable è ora memorizzato in una variabile se si desidera controllarlo
|
||||||
|
* Aggiunto: il trigger di ricarica ora può distinguere tra i tipi (AC, USB, wireless)
|
1
fastlane/metadata/android/it-IT/changelogs/141.txt
Normal file
1
fastlane/metadata/android/it-IT/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Il trigger del calendario è stato rimosso dalla versione Google
|
3
fastlane/metadata/android/it-IT/changelogs/142.txt
Normal file
3
fastlane/metadata/android/it-IT/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Risolto: trigger del calendario nascosto dalla versione Play
|
||||||
|
* Risolto: parametri non forniti correttamente all'avvio di altre app
|
||||||
|
* Risolto: arresto anomalo quando si esce dalle impostazioni mentre il servizio è in esecuzione
|
14
fastlane/metadata/android/nl-NL/changelogs/139.txt
Normal file
14
fastlane/metadata/android/nl-NL/changelogs/139.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
* Opgelost: overlay-toestemming voor het starten van een andere programmaactie is alleen vereist als startByActivity() is geselecteerd
|
||||||
|
* Opgelost: de trigger van de uitzendontvanger zou niets activeren, maar crashen
|
||||||
|
* Opgelost: bug in Android 14 (niet in Automation!!) vereiste een wijziging bij het kiezen van MMI-codes met een #-teken.
|
||||||
|
* Opgelost: opslagtoestemming kan worden weergegeven als niet verleend, zelfs als dit wel het geval was
|
||||||
|
* Opgelost: een zeer oude bugfix ook toegepast op F-Droid- en Google-Play-edities die per ongeluk alleen in de APK-editie waren geïmplementeerd (timeFrame-trigger met herhalingen)
|
||||||
|
* Opgelost: zeldzame crash tijdens het starten van de service
|
||||||
|
* Opgelost: gecompenseerd voor Android-wijzigingen, op tijd gebaseerde triggers zijn nu weer nauwkeurig
|
||||||
|
* Toegevoegd: nieuwe actie > screenshot maken
|
||||||
|
* Toegevoegd: Locatieservice (GPS) kan worden omgeschakeld tussen staten als WRITE_SECURE_SETTINGS is verleend vanaf een computer
|
||||||
|
* Toegevoegd: triggerUrl-actie kan nu worden gebruikt met POST en parameters
|
||||||
|
* Toegevoegd: Resultaat van triggerUrl-actie wordt nu opgeslagen in een variabele als u deze wilt controleren
|
||||||
|
* Toegevoegd: Nieuwe trigger: Agenda-afspraken
|
||||||
|
* Toegevoegd: Resultaat van runExecutable actie wordt nu opgeslagen in een variabele als u deze wilt controleren
|
||||||
|
* Toegevoegd: oplaadtrigger kan nu onderscheid maken tussen typen (AC, USB, draadloos)
|
1
fastlane/metadata/android/nl-NL/changelogs/141.txt
Normal file
1
fastlane/metadata/android/nl-NL/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Agendatrigger verwijderd uit Google-versie
|
3
fastlane/metadata/android/nl-NL/changelogs/142.txt
Normal file
3
fastlane/metadata/android/nl-NL/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Opgelost: kalendertrigger verborgen voor Play-versie
|
||||||
|
* Opgelost: parameters worden niet correct opgegeven bij het starten van andere apps
|
||||||
|
* Opgelost: crash bij het afsluiten van instellingen terwijl de service actief is
|
14
fastlane/metadata/android/pl-PL/changelogs/139.txt
Normal file
14
fastlane/metadata/android/pl-PL/changelogs/139.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
* Naprawiono: Uprawnienie nakładki do uruchamiania innej akcji programu jest wymagane tylko wtedy, gdy wybrano startByActivity()
|
||||||
|
* Naprawiono: Wyzwalacz odbiornika transmisji nie uruchamiał niczego, ale zawieszał się
|
||||||
|
* Naprawiono: Błąd w Androidzie 14 (nie w Automation!!) wymagał zmiany podczas wybierania kodów MMI zawierających znak #.
|
||||||
|
* Naprawiono: Uprawnienie do przechowywania może być wyświetlane jako nieprzyznane, nawet jeśli było
|
||||||
|
* Naprawiono: Zastosowano bardzo starą poprawkę błędu również do edycji F-Droid i Google-Play, która przez pomyłkę została zaimplementowana tylko w edycji APK (wyzwalacz timeFrame z powtórzeniami)
|
||||||
|
* Naprawiono: Rzadka awaria podczas uruchamiania usługi
|
||||||
|
* Naprawiono: Zrekompensowano zmiany w Androidzie, wyzwalacze oparte na czasie są teraz ponownie precyzyjne
|
||||||
|
* Dodano: nowa akcja -> zrób zrzut ekranu
|
||||||
|
* Dodano: Usługa lokalizacyjna (GPS) może być przełączana między stanami, jeśli WRITE_SECURE_SETTINGS została przyznana z komputera
|
||||||
|
* Dodano: akcja triggerUrl może być teraz używana z POST i parametrami
|
||||||
|
* Dodano: Wynik akcji triggerUrl jest teraz przechowywany w zmiennej, jeśli chcesz to sprawdzić
|
||||||
|
* Dodano: Nowy wyzwalacz: Wydarzenia w kalendarzu
|
||||||
|
* Dodano: Wynik akcji runExecutable jest teraz przechowywany w zmiennej, jeśli chcesz to sprawdzić
|
||||||
|
* Dodano: Wyzwalacz ładowania może teraz rozróżniać typy (AC, USB, bezprzewodowo)
|
1
fastlane/metadata/android/pl-PL/changelogs/141.txt
Normal file
1
fastlane/metadata/android/pl-PL/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Wyzwalacz kalendarza usunięty z wersji Google
|
3
fastlane/metadata/android/pl-PL/changelogs/142.txt
Normal file
3
fastlane/metadata/android/pl-PL/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Naprawiono: Wyzwalacz kalendarza ukryty w wersji Play
|
||||||
|
* Naprawiono: Parametry nie są poprawnie dostarczane podczas uruchamiania innych aplikacji
|
||||||
|
* Naprawiono: Awaria podczas wychodzenia z ustawień, gdy usługa jest uruchomiona
|
14
fastlane/metadata/android/ru-RU/changelogs/139.txt
Normal file
14
fastlane/metadata/android/ru-RU/changelogs/139.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
* Исправлено: Разрешение на оверлей для запуска других действий программы требуется только в том случае, если выбран startByActivity()
|
||||||
|
* Исправлено: Триггер широковещательного приемника не вызывал ничего, кроме сбоя.
|
||||||
|
* Исправлено: Ошибка в Android 14 (не в Automation!!) требовала изменения при наборе кодов MMI, содержащих символ #.
|
||||||
|
* Исправлено: Разрешение на хранение могло отображаться как не предоставленное, даже если оно было
|
||||||
|
* Исправлено: Применено очень старое исправление ошибки также к редакциям F-Droid и Google-Play, которые по ошибке были реализованы только в редакции APK (триггер timeFrame с повторами)
|
||||||
|
* Исправлено: редкий сбой при запуске сервиса.
|
||||||
|
* Исправлено: Компенсированы изменения Android, триггеры, основанные на времени, теперь снова точны
|
||||||
|
* Добавлено: новое действие -> сделать скриншот
|
||||||
|
* Добавлено: Служба определения местоположения (GPS) может переключаться между состояниями, если WRITE_SECURE_SETTINGS было предоставлено с компьютера.
|
||||||
|
* Добавлено: действие triggerUrl теперь можно использовать с POST и параметрами
|
||||||
|
* Добавлено: Результат действия triggerUrl теперь сохраняется в переменной, если вы хотите проверить это
|
||||||
|
* Добавлено: Новый триггер: События календаря
|
||||||
|
* Добавлено: Результат действия runExecutable теперь сохраняется в переменной, если вы хотите проверить это
|
||||||
|
* Добавлено: Триггер зарядки теперь может различать типы (переменный ток, USB, беспроводная связь)
|
1
fastlane/metadata/android/ru-RU/changelogs/141.txt
Normal file
1
fastlane/metadata/android/ru-RU/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Триггер календаря удален из версии Google
|
3
fastlane/metadata/android/ru-RU/changelogs/142.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* Исправлено: Триггер календаря скрыт в игровой версии
|
||||||
|
* Исправлено: Параметры неправильно указываются при запуске других приложений.
|
||||||
|
* Исправлено: Сбой при выходе из настроек во время работы сервиса
|
13
fastlane/metadata/android/zh-CN/changelogs/139.txt
Normal file
13
fastlane/metadata/android/zh-CN/changelogs/139.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
* 修复:只有在选择了 startByActivity() 时才需要启动其他程序操作的叠加权限
|
||||||
|
* 修复:广播接收机触发不会触发任何内容,但会崩溃
|
||||||
|
* 已修复:Android 14(不在 Automation!! 中)中的错误在拨打包含 # 字符的 MMI 代码时需要更改。
|
||||||
|
* 修复:存储权限可能显示为未授予,即使已授予
|
||||||
|
* 修复:将一个非常古老的错误修复也应用于 F-Droid 和 Google-Play 版本,这些版本错误地仅在 APK 版本中实现(具有重复的 timeFrame 触发器)
|
||||||
|
* 修复:启动服务时罕见崩溃
|
||||||
|
* 已修复:补偿了 Android 更改,基于时间的触发器现在再次精确
|
||||||
|
* 新增:新动作 ->截图 * 新增:定位服务 (GPS) 可以在各州之间切换,前提是已从计算机授予WRITE_SECURE_SETTINGS
|
||||||
|
* 新增:triggerUrl 操作现在可以与 POST 和参数一起使用
|
||||||
|
* 新增:triggerUrl 操作的结果现在存储在变量中,如果您想检查它
|
||||||
|
* 新增:新触发器:日历事件
|
||||||
|
* 新增:runExecutable 操作的结果现在存储在变量中,如果您想检查它
|
||||||
|
* 新增:充电触发器现在可以区分类型(交流、USB、无线)
|
1
fastlane/metadata/android/zh-CN/changelogs/141.txt
Normal file
1
fastlane/metadata/android/zh-CN/changelogs/141.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
* 日历触发器已从 Google 版本中删除
|
3
fastlane/metadata/android/zh-CN/changelogs/142.txt
Normal file
3
fastlane/metadata/android/zh-CN/changelogs/142.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* 修复:播放版本中隐藏的日历触发器
|
||||||
|
* 修复:启动其他应用程序时未正确提供参数的问题
|
||||||
|
* 修复:服务运行时退出设置时崩溃
|
Reference in New Issue
Block a user