29 Commits

Author SHA1 Message Date
a8646ef61d Merge branch 'accessibility_api' into development
# Conflicts:
#	app/src/main/java/com/jens/automation2/Actions.java
2023-12-19 16:54:52 +01:00
f641de9893 Take screenshot action added 2023-12-19 16:54:10 +01:00
bca8b44ad6 Bugfix for Android 14 for auto dialing mmi codes 2023-12-18 23:13:18 +01:00
c34dfa4af4 Bugfix for Android 14 for auto dialing mmi codes 2023-12-18 22:55:18 +01:00
38644cee28 Take screenshot action added 2023-12-16 13:52:18 +01:00
47898e84ea Comment added 2023-12-14 17:46:55 +01:00
ac74b52aed Accessibility API 2023-12-14 00:15:59 +01:00
3f76813e80 Http method selectable 2023-12-12 23:40:12 +01:00
1b8dc5de5f Http method selectable 2023-12-11 22:50:07 +01:00
3c8c0f14f2 Fixed bug in broadcast receiver trigger 2023-12-06 23:44:40 +01:00
9ead47bdf7 Permissions for startActivity() reduced 2023-12-03 23:24:58 +01:00
e4828a9720 Fixes for Google Play version 2023-11-30 00:00:34 +01:00
4f971e8a1b New version 2023-11-25 23:23:58 +01:00
34fbc1d005 New version prepared 2023-11-24 23:57:26 +01:00
b72049defc Start other service bugfix attempt 2023-11-22 23:20:26 +01:00
54f3cc84c4 Start other service bugfix attempt 2023-11-19 23:44:10 +01:00
7884358564 Start other service bugfix attempt 2023-11-08 00:15:39 +01:00
f24c9f99dc startService() experiments 2023-11-05 16:20:48 +01:00
64b97c650d Small changes 2023-10-28 23:20:07 +02:00
9daf4c4747 Small changes 2023-10-27 23:59:12 +02:00
94f7936c4a ActivityDetection permission fixed 2023-10-26 23:30:45 +02:00
02f7b642cf Wifi trigger hint 2023-10-23 23:44:21 +02:00
8d10bf05af Escaped variables when triggering 2023-10-19 22:30:13 +02:00
8c0cee9589 Wifi trigger fix attempt 2023-10-15 23:54:27 +02:00
6b23bd6733 Icon restored 2023-08-31 15:21:55 +02:00
1a60c88f35 Merge remote-tracking branch 'origin/development' into development
# Conflicts:
#	fastlane/metadata/android/en-US/changelogs/134.txt
2023-08-30 23:25:13 +02:00
3312d99177 Changes icon in Play store version 2023-08-30 23:23:58 +02:00
ea01806915 Charging trigger bug fixed 2023-08-24 20:04:05 +02:00
36173f2fcb device admin permission added for start phone call action 2023-08-01 22:59:05 +02:00
69 changed files with 950 additions and 181 deletions

View File

@@ -11,8 +11,8 @@ android {
compileSdkVersion 31
buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy'
versionCode 133
versionName "1.7.17"
versionCode 138
versionName "1.7.21"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -36,7 +36,7 @@ android {
{
dimension "version"
versionNameSuffix "-googlePlay"
targetSdkVersion 31
targetSdkVersion 33
}
/*

View File

@@ -87,7 +87,7 @@
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="@drawable/gears"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
@@ -261,6 +261,17 @@
android:exported="true"
/>
<service android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/config_accessibility_service" />
</service>
</application>
</manifest>

View File

@@ -85,7 +85,7 @@
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="@drawable/gears"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
@@ -246,6 +246,17 @@
android:exported="true"
/>
<service android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/config_accessibility_service" />
</service>
</application>
</manifest>

View File

@@ -65,12 +65,11 @@
<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.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="@drawable/gears"
android:icon="@drawable/crane"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
@@ -246,6 +245,17 @@
android:exported="true"
/>
<service android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/config_accessibility_service" />
</service>
</application>
</manifest>

View File

@@ -56,6 +56,7 @@ public class Action
startPhoneCall,
stopPhoneCall,
copyToClipboard,
takeScreenshot,
sendTextMessage;
public String getFullName(Context context)
@@ -140,6 +141,9 @@ public class Action
return context.getResources().getString(R.string.endPhoneCall);
case copyToClipboard:
return context.getResources().getString(R.string.copyTextToClipboard);
case takeScreenshot:
return context.getResources().getString(R.string.takeScreenshot);
default:
return "Unknown";
}
@@ -307,6 +311,10 @@ public class Action
break;
case copyToClipboard:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.copyTextToClipboard));
break;
case takeScreenshot:
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.takeScreenshot));
break;
default:
returnString.append(action.toString());
}
@@ -632,6 +640,9 @@ public class Action
case copyToClipboard:
Actions.copyToClipboard(context, Miscellaneous.replaceVariablesInText(this.getParameter2(), context));
break;
case takeScreenshot:
Actions.takeScreenshot();
break;
default:
Miscellaneous.logEvent("w", "Action", context.getResources().getString(R.string.unknownActionSpecified), 3);
break;
@@ -648,6 +659,7 @@ public class Action
{
String username = null;
String password = null;
String method = ActivityManageActionTriggerUrl.methodGet;
String url;
String[] components = getParameter2().split(";");
@@ -657,6 +669,9 @@ public class Action
username = components[0];
password = components[1];
url = components[2];
if(components.length >= 4)
method = components[3];
}
else // compatibility for very old versions which haven't upgraded, yet.
url = components[0];
@@ -670,7 +685,7 @@ public class Action
Miscellaneous.logEvent("i", "HTTP", "Attempting download of " + url, 4); //getResources().getString("attemptingDownloadOf");
if(this.getParameter1()) // use authentication
new DownloadTask().execute(url, username, password);
new DownloadTask().execute(url, username, password, method);
else
new DownloadTask().execute(url, null, null);
}
@@ -692,16 +707,19 @@ public class Action
String urlUsername = null;
String urlPassword = null;
String method = ActivityManageActionTriggerUrl.methodGet;
if(parameters.length >= 3)
{
urlUsername=parameters[1];
urlPassword=parameters[2];
urlUsername = parameters[1];
urlPassword = parameters[2];
if(parameters.length >= 4)
method = parameters[3];
}
String response = "httpError";
HttpGet post;
if(Settings.httpAttempts < 1)
if(Settings.httpAttempts < 1)
Miscellaneous.logEvent("w", "HTTP Request", Miscellaneous.getAnyContext().getResources().getString(R.string.cantDownloadTooFewRequestsInSettings), 3);
while(attempts <= Settings.httpAttempts && response.equals("httpError"))
@@ -710,9 +728,9 @@ public class Action
// Either thorough checking or no encryption
if(!Settings.httpAcceptAllCertificates || !urlString.toLowerCase(Locale.getDefault()).contains("https"))
response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword);
response = Miscellaneous.downloadURL(urlString, urlUsername, urlPassword, method);
else
response = Miscellaneous.downloadURLwithoutCertificateChecking(urlString, urlUsername, urlPassword);
response = Miscellaneous.downloadURLwithoutCertificateChecking(urlString, urlUsername, urlPassword, method);
try
{

View File

@@ -1,6 +1,7 @@
package com.jens.automation2;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.NotificationManager;
@@ -10,6 +11,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
@@ -1042,11 +1044,16 @@ public class Actions
{
Miscellaneous.logEvent("i", "StartOtherActivity", "Starting other Activity...", 4);
String params[] = param.split(";");
String params[];
if(param.contains(Action.actionParameter2Split))
params = param.split(Action.actionParameter2Split);
else
params = param.split(";");
try
{
Intent externalActivityIntent;
Intent externalApplicationIntent;
if (!startByAction)
{
@@ -1059,15 +1066,15 @@ public class Actions
Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by activity: " + packageName + " " + className, 3);
externalActivityIntent = new Intent(Intent.ACTION_MAIN);
externalActivityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
externalApplicationIntent = new Intent(Intent.ACTION_MAIN);
externalApplicationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// if(packageName.equals("dummyPkg"))
// externalActivityIntent.setAction(className);
// else
externalActivityIntent.setClassName(packageName, className);
if(packageName.equals("dummyPkg"))
externalApplicationIntent.setAction(className);
if (!Miscellaneous.doesActivityExist(externalActivityIntent, Miscellaneous.getAnyContext()))
externalApplicationIntent.setClassName(packageName, className);
if (!Miscellaneous.doesActivityExist(externalApplicationIntent, Miscellaneous.getAnyContext()))
Miscellaneous.logEvent("w", "StartOtherApp", "Activity not found: " + className, 2);
}
else
@@ -1075,25 +1082,32 @@ public class Actions
// selected by action
Miscellaneous.logEvent("i", "StartOtherApp", "Starting app by action: " + param, 3);
externalActivityIntent = new Intent();
externalApplicationIntent = new Intent();
if (!params[0].equals(dummyPackageString))
externalActivityIntent.setPackage(params[0]);
externalApplicationIntent.setPackage(params[0]);
externalActivityIntent.setAction(params[1]);
externalApplicationIntent.setAction(params[1]);
if (params[2].equals(ActivityManageActionStartActivity.startByServiceString) || params[2].equals(ActivityManageActionStartActivity.startByForegroundServiceString))
{
externalApplicationIntent.setComponent(new ComponentName(params[0], params[2]));
}
}
externalActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
externalApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Pack intents
externalActivityIntent = packParametersIntoIntent(externalActivityIntent, params, 3);
externalApplicationIntent = packParametersIntoIntent(externalApplicationIntent, params, 3);
if (params[2].equals(ActivityManageActionStartActivity.startByActivityString))
automationServerRef.startActivity(externalActivityIntent);
if (params[2].equals(ActivityManageActionStartActivity.startByServiceString))
automationServerRef.startService(externalActivityIntent);
automationServerRef.startActivity(externalApplicationIntent);
else if (params[2].equals(ActivityManageActionStartActivity.startByServiceString))
automationServerRef.startService(externalApplicationIntent);
else if (params[2].equals(ActivityManageActionStartActivity.startByForegroundServiceString) && Build.VERSION.SDK_INT >= 26)
automationServerRef.startForegroundService(externalApplicationIntent);
else
automationServerRef.sendBroadcast(externalActivityIntent);
automationServerRef.sendBroadcast(externalApplicationIntent);
}
catch (Exception e)
{
@@ -2273,7 +2287,18 @@ public class Actions
public static void startPhoneCall(Context context, String phoneNumber)
{
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode(phoneNumber)));
Intent intent;
/*
Bug in Android 14 makes it necessary to add double quotes around MMI code.
More precisely it's required for codes containing the # character.
*/
if(Build.VERSION.SDK_INT >= 34)
intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode("\"" + phoneNumber + "\"")));
else
intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + Uri.encode(phoneNumber)));
// intent.setClassName("com.android.phone","com.android.phone.OutgoingCallBroadcaster");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
@@ -2326,4 +2351,12 @@ public class Actions
clipboard.setPrimaryClip(clip);
}
}
public static void takeScreenshot()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
{
MyAccessibilityService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
}
}
}

View File

@@ -29,6 +29,7 @@ import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Toast;
@@ -48,17 +49,19 @@ public class ActivityManageActionStartActivity extends Activity
*/
ListView lvIntentPairs;
EditText etParameterName, etParameterValue, etPackageName, etActivityOrActionPath;
EditText etParameterName, etParameterValue, etPackageName, etActivityOrActionPath, etClassName;
Button bSelectApp, bAddIntentPair, bSaveActionStartOtherActivity, showStartProgramExamples;
Spinner spinnerParameterType;
RadioGroup rgAppStartupType;
boolean edit = false;
ProgressDialog progressDialog = null;
RadioButton rbStartAppSelectByActivity, rbStartAppSelectByAction, rbStartAppByActivity, rbStartAppByBroadcast, rbStartAppByService;
RadioButton rbStartAppSelectByActivity, rbStartAppSelectByAction, rbStartAppByActivity, rbStartAppByBroadcast, rbStartAppByService, rbStartAppByForegroundService;
final String urlShowExamples = "https://server47.de/automation/examples_startProgram.html";
final static String startByActivityString = "0";
final static String startByBroadcastString = "1";
final static String startByServiceString = "2";
public final static String startByActivityString = "0";
public final static String startByBroadcastString = "1";
public final static String startByServiceString = "2";
public final static String startByForegroundServiceString = "3";
final static int requestCodeForRequestQueryAllPackagesPermission = 4711;
@@ -72,6 +75,7 @@ public class ActivityManageActionStartActivity extends Activity
lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs);
etParameterName = (EditText)findViewById(R.id.etParameterName);
etParameterValue = (EditText)findViewById(R.id.etParameterValue);
etClassName = (EditText)findViewById(R.id.etClassName);
bSelectApp = (Button)findViewById(R.id.bSelectApp);
bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair);
bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity);
@@ -84,13 +88,16 @@ public class ActivityManageActionStartActivity extends Activity
rbStartAppByActivity = (RadioButton)findViewById(R.id.rbStartAppByActivity);
rbStartAppByBroadcast = (RadioButton)findViewById(R.id.rbStartAppByBroadcast);
rbStartAppByService = (RadioButton)findViewById(R.id.rbStartAppByService);
rbStartAppByForegroundService = (RadioButton)findViewById(R.id.rbStartAppByForegroundService);
rgAppStartupType = (RadioGroup)findViewById(R.id.rgAppStartupType);
intentTypeSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageActionStartActivity.supportedIntentTypes);
spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
intentTypeSpinnerAdapter.notifyDataSetChanged();
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
etClassName.setEnabled(false);
intentPairAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, intentPairList);
bSelectApp.setOnClickListener(new OnClickListener()
{
@Override
@@ -227,23 +234,29 @@ public class ActivityManageActionStartActivity extends Activity
String parameter2 = "";
if (rbStartAppSelectByActivity.isChecked())
parameter2 += etPackageName.getText().toString() + ";" + etActivityOrActionPath.getText().toString();
else {
parameter2 += etPackageName.getText().toString() + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
else
{
if (etPackageName.getText().toString() != null && etPackageName.getText().toString().length() > 0)
parameter2 += etPackageName.getText().toString() + ";" + etActivityOrActionPath.getText().toString();
parameter2 += etPackageName.getText().toString() + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
else
parameter2 += Actions.dummyPackageString + ";" + etActivityOrActionPath.getText().toString();
parameter2 += Actions.dummyPackageString + Action.actionParameter2Split + etActivityOrActionPath.getText().toString();
// if(etClassName.getText().toString().length() > 0)
parameter2 += Action.actionParameter2Split + etClassName.getText().toString();
}
if (rbStartAppByActivity.isChecked())
parameter2 += ";" + startByActivityString;
parameter2 += Action.actionParameter2Split + startByActivityString;
else if(rbStartAppByService.isChecked())
parameter2 += ";" + startByServiceString;
parameter2 += Action.actionParameter2Split + startByServiceString;
else if(rbStartAppByForegroundService.isChecked())
parameter2 += Action.actionParameter2Split + startByForegroundServiceString;
else
parameter2 += ";" + startByBroadcastString;
parameter2 += Action.actionParameter2Split + startByBroadcastString;
for (String s : intentPairList)
parameter2 += ";" + s;
parameter2 += Action.actionParameter2Split + s;
returnData.putExtra(ActivityManageRule.intentNameActionParameter2, parameter2);
@@ -290,7 +303,9 @@ public class ActivityManageActionStartActivity extends Activity
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
{
bSelectApp.setEnabled(isChecked);
}
}
});
@@ -304,6 +319,23 @@ public class ActivityManageActionStartActivity extends Activity
}
});
rgAppStartupType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i)
{
if(rbStartAppByActivity.isChecked())
etClassName.setEnabled(false);
else if (rbStartAppByBroadcast.isChecked())
etClassName.setEnabled(false);
else if(rbStartAppByService.isChecked())
etClassName.setEnabled(true);
else if(rbStartAppByForegroundService.isChecked())
etClassName.setEnabled(true);
}
});
Intent i = getIntent();
if(i.hasExtra(ActivityManageRule.intentNameActionParameter1))
loadValuesIntoGui(i);
@@ -596,11 +628,27 @@ public class ActivityManageActionStartActivity extends Activity
rbStartAppSelectByActivity.setChecked(!selectionByAction);
rbStartAppSelectByAction.setChecked(selectionByAction);
String[] params = input.getStringExtra(ActivityManageRule.intentNameActionParameter2).split(";");
String[] params;
String partsString = input.getStringExtra(ActivityManageRule.intentNameActionParameter2);
rbStartAppByActivity.setChecked(params[2].equals(startByActivityString));
rbStartAppByBroadcast.setChecked(params[2].equals(startByBroadcastString));
rbStartAppByService.setChecked(params[2].equals(startByServiceString));
if(partsString.contains(Action.actionParameter2Split))
params = partsString.split(Action.actionParameter2Split);
else
params = partsString.split(";");
if(Miscellaneous.isNumeric(params[2])) // old configuration file
{
rbStartAppByActivity.setChecked(params[2].equals(startByActivityString));
rbStartAppByBroadcast.setChecked(params[2].equals(startByBroadcastString));
rbStartAppByService.setChecked(params[2].equals(startByServiceString));
}
else
{
rbStartAppByActivity.setChecked(params[3].equals(startByActivityString));
rbStartAppByBroadcast.setChecked(params[3].equals(startByBroadcastString));
rbStartAppByService.setChecked(params[3].equals(startByServiceString));
rbStartAppByForegroundService.setChecked(params[3].equals(startByForegroundServiceString));
}
int startIndex = -1;
@@ -615,10 +663,11 @@ public class ActivityManageActionStartActivity extends Activity
etPackageName.setText(params[0]);
etActivityOrActionPath.setText(params[1]);
etClassName.setText(params[2]);
}
if (params.length >= 3)
startIndex = 3;
if (params.length >= 4)
startIndex = 4;
if(startIndex > -1 && params.length > startIndex)
{

View File

@@ -13,6 +13,7 @@ import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TableLayout;
import android.widget.Toast;
@@ -26,11 +27,15 @@ public class ActivityManageActionTriggerUrl extends Activity
EditText etTriggerUrl, etTriggerUrlUsername, etTriggerUrlPassword;
ListView lvTriggerUrlPostParameters;
CheckBox chkTriggerUrlUseAuthentication;
RadioButton rbTriggerUrlMethodGet, rbTriggerUrlMethodPost;
TableLayout tlTriggerUrlAuthentication;
ArrayAdapter<Map<String,String>> lvTriggerUrlPostParametersAdapter;
// private String existingUrl = "";
public static final String methodGet = "GET";
public static final String methodPost = "POST";
public static boolean edit = false;
public static Action resultingAction = null;
@@ -49,6 +54,9 @@ public class ActivityManageActionTriggerUrl extends Activity
lvTriggerUrlPostParameters = (ListView)findViewById(R.id.lvTriggerUrlPostParameters);
tlTriggerUrlAuthentication = (TableLayout)findViewById(R.id.tlTriggerUrlAuthentication);
bSaveTriggerUrl = (Button)findViewById(R.id.bSaveSpeakText);
rbTriggerUrlMethodGet = (RadioButton) findViewById(R.id.rbTriggerUrlMethodGet);
rbTriggerUrlMethodPost = (RadioButton) findViewById(R.id.rbTriggerUrlMethodPost);
bSaveTriggerUrl.setOnClickListener(new OnClickListener()
{
@Override
@@ -59,6 +67,8 @@ public class ActivityManageActionTriggerUrl extends Activity
if(resultingAction == null)
{
resultingAction = new Action();
}
resultingAction.setAction(Action_Enum.triggerUrl);
resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
@@ -70,13 +80,18 @@ public class ActivityManageActionTriggerUrl extends Activity
if(password == null)
password = "";
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
ActivityManageActionTriggerUrl.resultingAction.setParameter2(
username + ";" +
password + ";" +
etTriggerUrl.getText().toString().trim()
etTriggerUrl.getText().toString().trim() + ";" +
method
);
}
backToRuleManager();
}
else
@@ -84,16 +99,25 @@ public class ActivityManageActionTriggerUrl extends Activity
}
});
chkTriggerUrlUseAuthentication.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
{
tlTriggerUrlAuthentication.setVisibility(View.VISIBLE);
rbTriggerUrlMethodGet.setChecked(false);
rbTriggerUrlMethodPost.setChecked(true);
rbTriggerUrlMethodGet.setEnabled(false);
rbTriggerUrlMethodPost.setEnabled(false);
}
else
{
tlTriggerUrlAuthentication.setVisibility(View.GONE);
rbTriggerUrlMethodGet.setEnabled(true);
rbTriggerUrlMethodPost.setEnabled(true);
}
etTriggerUrlUsername.setEnabled(isChecked);
etTriggerUrlPassword.setEnabled(isChecked);
@@ -109,7 +133,6 @@ public class ActivityManageActionTriggerUrl extends Activity
}
});
updateListView();
ActivityManageActionTriggerUrl.edit = getIntent().getBooleanExtra("edit", false);
if(edit)
@@ -123,6 +146,20 @@ public class ActivityManageActionTriggerUrl extends Activity
chkTriggerUrlUseAuthentication.setChecked(ActivityManageActionTriggerUrl.resultingAction.getParameter1());
etTriggerUrlUsername.setText(components[0]);
etTriggerUrlPassword.setText(components[1]);
if(components.length >= 4)
{
switch(components[3])
{
case methodPost:
rbTriggerUrlMethodPost.setChecked(true);
break;
case methodGet:
default:
rbTriggerUrlMethodGet.setChecked(true);
break;
}
}
}
else
etTriggerUrl.setText(components[0]);
@@ -141,13 +178,18 @@ public class ActivityManageActionTriggerUrl extends Activity
if(password == null)
password = "";
String method = methodGet;
if(rbTriggerUrlMethodPost.isChecked())
method = methodPost;
ActivityManageActionTriggerUrl.resultingAction.setParameter1(chkTriggerUrlUseAuthentication.isChecked());
ActivityManageActionTriggerUrl.resultingAction.setParameter2(
username + ";" +
password + ";" +
etTriggerUrl.getText().toString()
etTriggerUrl.getText().toString() + ";" +
method
);
}

View File

@@ -2126,6 +2126,8 @@ public class ActivityManageRule extends Activity
}
else if(types[i].toString().equals(Action_Enum.copyToClipboard.toString()))
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
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@@ -2352,6 +2354,12 @@ public class ActivityManageRule extends Activity
Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionCopyToClipboard.class);
startActivityForResult(intent, requestCodeActionCopyTextToClipboardAdd);
}
else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.takeScreenshot.toString()))
{
newAction.setAction(Action_Enum.takeScreenshot);
ruleToEdit.getActionSet().add(newAction);
refreshActionList();
}
}
});

View File

@@ -12,11 +12,15 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Spinner;
@@ -43,7 +47,7 @@ public class ActivityManageTriggerWifi extends Activity
List<String> wifiList = new ArrayList<>();
ArrayAdapter<String> wifiSpinnerAdapter;
private final static int requestCodeLocationPermission = 124;
TextView tvWifiTriggerNameLocationNotice;
TextView tvWifiTriggerNameLocationNotice, tvWifiTriggerDisconnectionHint;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
@@ -59,6 +63,9 @@ public class ActivityManageTriggerWifi extends Activity
bTriggerWifiSave = (Button) findViewById(R.id.bTriggerWifiSave);
bLoadWifiList = (Button) findViewById(R.id.bLoadWifiList);
tvWifiTriggerNameLocationNotice = (TextView)findViewById(R.id.tvWifiTriggerNameLocationNotice);
tvWifiTriggerDisconnectionHint = (TextView)findViewById(R.id.tvWifiTriggerDisconnectionHint);
tvWifiTriggerDisconnectionHint.setVisibility(View.GONE);
wifiSpinnerAdapter = new ArrayAdapter<String>(this, R.layout.text_view_for_poi_listview_mediumtextsize, wifiList);
spinnerWifiList.setAdapter(wifiSpinnerAdapter);
@@ -101,6 +108,11 @@ public class ActivityManageTriggerWifi extends Activity
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
etTriggerWifiName.setText(wifiList.get(position));
if(etTriggerWifiName.getText().toString().length() > 0 && rbTriggerWifiDisconnected.isChecked())
tvWifiTriggerDisconnectionHint.setVisibility(View.VISIBLE);
else
tvWifiTriggerDisconnectionHint.setVisibility(View.GONE);
}
@Override
@@ -118,6 +130,41 @@ public class ActivityManageTriggerWifi extends Activity
loadWifis();
}
});
rbTriggerWifiDisconnected.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
if(etTriggerWifiName.getText().toString().length() > 0 && b)
tvWifiTriggerDisconnectionHint.setVisibility(View.VISIBLE);
else
tvWifiTriggerDisconnectionHint.setVisibility(View.GONE);
}
});
etTriggerWifiName.addTextChangedListener(new TextWatcher()
{
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
if(etTriggerWifiName.getText().toString().length() > 0 && rbTriggerWifiDisconnected.isChecked())
tvWifiTriggerDisconnectionHint.setVisibility(View.VISIBLE);
else
tvWifiTriggerDisconnectionHint.setVisibility(View.GONE);
}
@Override
public void afterTextChanged(Editable editable)
{
}
});
}
public void loadWifis()

View File

@@ -18,6 +18,7 @@ import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -51,12 +52,13 @@ public class ActivityPermissions extends Activity
private static final int requestCodeForPermissionsBatteryOptimization = 12048;
private static final int requestCodeForPermissionNotificationAccessAndroid13 = 12049;
private static final int requestCodeForPermissionsManageOverlay = 12050;
private static final int requestCodeForPermissionsAccessibility = 12051;
protected String[] specificPermissionsToRequest = null;
public static String intentExtraName = "permissionsToBeRequested";
Button bCancelPermissions, bRequestPermissions;
TextView tvPermissionsExplanation, tvPermissionsExplanationSystemSettings, tvPermissionsExplanationLong;
TextView tvPermissionsExplanation, tvPermissionsExplanationSystemSettings, tvPermissionsExplanationLong, tvRestrictionPermissionsNotice;
static ActivityPermissions instance = null;
public final static String permissionNameWireguard = "com.wireguard.android.permission.CONTROL_TUNNELS";
@@ -87,6 +89,7 @@ public class ActivityPermissions extends Activity
tvPermissionsExplanation = (TextView)findViewById(R.id.tvPermissionsExplanation);
tvPermissionsExplanationSystemSettings = (TextView)findViewById(R.id.tvPermissionsExplanationSystemSettings);
tvPermissionsExplanationLong = (TextView)findViewById(R.id.tvPermissionsExplanationLong);
tvRestrictionPermissionsNotice = (TextView)findViewById(R.id.tvRestrictionPermissionsNotice);
bCancelPermissions.setOnClickListener(new View.OnClickListener()
{
@@ -305,6 +308,10 @@ public class ActivityPermissions extends Activity
{
return android.provider.Settings.canDrawOverlays(Miscellaneous.getAnyContext());
}
else if(s.equals(Manifest.permission.BIND_ACCESSIBILITY_SERVICE))
{
return haveAccessibilityAccess(Miscellaneous.getAnyContext());
}
else
{
int res = context.checkCallingOrSelfPermission(s);
@@ -323,11 +330,59 @@ public class ActivityPermissions extends Activity
return active;
}
public static boolean haveAccessibilityAccess(Context mContext)
{
int accessibilityEnabled = 0;
final String service = mContext.getPackageName() + "/" + BuildConfig.APPLICATION_ID + ".MyAccessibilityService";
boolean accessibilityFound = false;
try
{
accessibilityEnabled = Settings.Secure.getInt(mContext.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
// Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
}
catch (Settings.SettingNotFoundException e)
{
// Log.e(TAG, "Error finding setting, default accessibility to not found: " + e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1)
{
String settingValue = Settings.Secure.getString(mContext.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null)
{
TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
splitter.setString(settingValue);
while (splitter.hasNext())
{
String accessibilityService = splitter.next();
if (accessibilityService.equalsIgnoreCase(service))
{
return true;
}
}
}
}
return accessibilityFound;
}
public static void requestOverlay()
{
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
ActivityPermissions.getInstance().startActivityForResult(intent, requestCodeForPermissionsManageOverlay);
}
public static void requestBindAccessibilityService()
{
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ActivityPermissions.getInstance().startActivityForResult(intent, requestCodeForPermissionsAccessibility);
}
public static void requestDeviceAdmin()
{
if(!haveDeviceAdmin())
@@ -370,10 +425,13 @@ public class ActivityPermissions extends Activity
if(!havePermission(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, workingContext))
addToArrayListUnique(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, requiredPermissions);
for(Profile p : Profile.getProfileCollection())
if(!havePermission(Manifest.permission.READ_EXTERNAL_STORAGE, workingContext))
{
if(p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
for (Profile p : Profile.getProfileCollection())
{
if (p.changeIncomingCallsRingtone || p.changeNotificationRingtone)
addToArrayListUnique(Manifest.permission.READ_EXTERNAL_STORAGE, requiredPermissions);
}
}
if (!onlyGeneral)
@@ -407,27 +465,6 @@ public class ActivityPermissions extends Activity
}
}
}
/*
Not all permissions need to be asked for.
*/
/*if(shouldShowRequestPermissionRationale("android.permission.RECORD_AUDIO"))
Toast.makeText(ActivityMainScreen.this, "shouldShowRequestPermissionRationale", Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivityMainScreen.this, "not shouldShowRequestPermissionRationale", Toast.LENGTH_LONG).show();*/
// addToArrayListUnique("Manifest.permission.RECORD_AUDIO", requiredPermissions);
/*int hasPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO);
if (hasPermission == PackageManager.PERMISSION_DENIED)
{
Toast.makeText(ActivityMainScreen.this, "Don't have record_audio. Requesting...", Toast.LENGTH_LONG).show();
// requestPermissions(new String[]{"Manifest.permission.CAMERA"}, requestCodeForPermissions);
ActivityCompat.requestPermissions(ActivityMainScreen.this, new String[]{"Manifest.permission.CAMERA"}, requestCodeForPermissions);
}
else
Toast.makeText(ActivityMainScreen.this, "Have record_audio.", Toast.LENGTH_LONG).show();*/
}
return requiredPermissions.toArray(new String[requiredPermissions.size()]);
@@ -456,7 +493,8 @@ public class ActivityPermissions extends Activity
{
case activityDetection:
addToArrayListUnique(permissionNameGoogleActivityDetection, requiredPermissions);
addToArrayListUnique(Manifest.permission.ACTIVITY_RECOGNITION, requiredPermissions);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
addToArrayListUnique(Manifest.permission.ACTIVITY_RECOGNITION, requiredPermissions);
break;
case airplaneMode:
addToArrayListUnique(Manifest.permission.ACCESS_NETWORK_STATE, requiredPermissions);
@@ -649,7 +687,18 @@ public class ActivityPermissions extends Activity
// )
// addToArrayListUnique("net.kollnig.missioncontrol.permission.ADMIN", requiredPermissions);
if(Build.VERSION.SDK_INT >= 29)
addToArrayListUnique(Manifest.permission.SYSTEM_ALERT_WINDOW, requiredPermissions);
{
String parts[];
if(action.getParameter2().contains(Action.actionParameter2Split))
parts = action.getParameter2().split(Action.actionParameter2Split);
else
parts = action.getParameter2().split(";");
// Permission only required for starts of activity, not broadcasts or services
if(parts[2].equals(ActivityManageActionStartActivity.startByActivityString))
addToArrayListUnique(Manifest.permission.SYSTEM_ALERT_WINDOW, requiredPermissions);
}
break;
case triggerUrl:
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
@@ -705,11 +754,13 @@ public class ActivityPermissions extends Activity
break;
case startPhoneCall:
addToArrayListUnique(Manifest.permission.CALL_PHONE, requiredPermissions);
// addToArrayListUnique(Manifest.permission.SYSTEM_ALERT_WINDOW, requiredPermissions);
addToArrayListUnique(Manifest.permission.SYSTEM_ALERT_WINDOW, requiredPermissions);
break;
case stopPhoneCall:
addToArrayListUnique(Manifest.permission.ANSWER_PHONE_CALLS, requiredPermissions);
break;
case takeScreenshot:
addToArrayListUnique(Manifest.permission.BIND_ACCESSIBILITY_SERVICE, requiredPermissions);
default:
break;
}
@@ -909,6 +960,8 @@ public class ActivityPermissions extends Activity
case Manifest.permission.SYSTEM_ALERT_WINDOW:
for(String ruleName : getRulesUsing(Action.Action_Enum.startOtherActivity))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Action.Action_Enum.startPhoneCall))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.ANSWER_PHONE_CALLS:
for(String ruleName : getRulesUsing(Action.Action_Enum.stopPhoneCall))
@@ -957,6 +1010,10 @@ public class ActivityPermissions extends Activity
case Manifest.permission.QUERY_ALL_PACKAGES:
usingElements.add(getResources().getString(R.string.queryAllPackages));
break;
case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
for(String ruleName : getRulesUsing(Action.Action_Enum.takeScreenshot))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
}
return usingElements;
@@ -965,6 +1022,15 @@ public class ActivityPermissions extends Activity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
/*
All of the following permissions need to be "manually" activated by the user in some
buried system menu.
In my opinion by mistake the function will be called when the user has just landed
on one of those screens, not when he exits it again. To compensate for that onResume()
is overridden. This enables the permission screen to automatically close after all
required permissions have been granted.
*/
super.onActivityResult(requestCode, resultCode, data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
@@ -1012,6 +1078,10 @@ public class ActivityPermissions extends Activity
if (requestCode == requestCodeForPermissionsManageOverlay)
if(havePermission(Manifest.permission.SYSTEM_ALERT_WINDOW, ActivityPermissions.this))
requestPermissions(cachedPermissionsToRequest, true);
if (requestCode == requestCodeForPermissionsAccessibility)
if(havePermission(Manifest.permission.BIND_ACCESSIBILITY_SERVICE, ActivityPermissions.this))
requestPermissions(cachedPermissionsToRequest, true);
}
}
@@ -1071,10 +1141,14 @@ public class ActivityPermissions extends Activity
}
else if (s.equalsIgnoreCase(Manifest.permission.ACCESS_NOTIFICATION_POLICY))
{
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_apk))
Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.noticeRestrictedPermissions), ActivityPermissions.this).show();
requiredPermissions.remove(s);
cachedPermissionsToRequest = requiredPermissions;
Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivityForResult(intent, requestCodeForPermissionsNotificationPolicy);
return;
}
else if (s.equalsIgnoreCase(Manifest.permission.SYSTEM_ALERT_WINDOW))
@@ -1093,6 +1167,22 @@ public class ActivityPermissions extends Activity
diag.show();
return;
}
else if (s.equalsIgnoreCase(Manifest.permission.BIND_ACCESSIBILITY_SERVICE))
{
AlertDialog diag = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.accessibilityApiPermissionHint), ActivityPermissions.this);
diag.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
requiredPermissions.remove(s);
cachedPermissionsToRequest = requiredPermissions;
requestBindAccessibilityService();
}
});
diag.show();
return;
}
else if (s.equalsIgnoreCase(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE))
{
if(Build.VERSION.SDK_INT >= 33)
@@ -1575,4 +1665,47 @@ public class ActivityPermissions extends Activity
return false;
}
}
@Override
protected void onResume()
{
super.onResume();
if(Build.VERSION.SDK_INT >= 33 && BuildConfig.FLAVOR.equals(AutomationService.flavor_name_apk))
{
for (String p : getRequiredPermissions(false))
{
if (p.equals(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE) || p.equals(Manifest.permission.BIND_ACCESSIBILITY_SERVICE))
{
tvRestrictionPermissionsNotice.setText(getResources().getString(R.string.noticeRestrictedPermissions));
/*
Opening the app's settings directly does not work because the
mentioned 3 dots are only displayed when you went there the hard way.
*/
/*
tvRestrictionPermissionsNotice.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
})*/;
break;
}
}
}
for(String p : getRequiredPermissions(false))
{
if(!havePermission(p, this))
return;
}
// have all
setHaveAllPermissions();
}
}

View File

@@ -22,7 +22,7 @@ public class AsyncTasks
try
{
String result = Miscellaneous.downloadURL("https://server47.de/automation/?action=getLatestVersionCode", null, null).trim();
String result = Miscellaneous.downloadURL("https://server47.de/automation/?action=getLatestVersionCode", null, null, ActivityManageActionTriggerUrl.methodGet).trim();
int latestVersion = Integer.parseInt(result);
// At this point the update check itself has already been successful.

View File

@@ -223,7 +223,10 @@ public class AutomationService extends Service implements OnInitListener
startUpRoutine();
Intent myIntent = new Intent(this, ActivityMainTabLayout.class);
myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0);
if(getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_MUTABLE);
else
myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0);
notificationBuilder = createServiceNotificationBuilder();
updateNotification();
@@ -518,7 +521,12 @@ public class AutomationService extends Service implements OnInitListener
builder.setContentTitle("Automation");
if(Settings.showIconWhenServiceIsRunning)
builder.setSmallIcon(R.drawable.ic_launcher);
{
if(BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))
builder.setSmallIcon(R.drawable.crane);
else
builder.setSmallIcon(R.drawable.ic_launcher);
}
builder.setCategory(Notification.CATEGORY_SERVICE);
builder.setWhen(System.currentTimeMillis());
@@ -526,7 +534,7 @@ public class AutomationService extends Service implements OnInitListener
Notification defaultNotification = builder.build();
defaultNotification.icon = R.drawable.ic_launcher;
defaultNotification.icon = R.drawable.crane;
defaultNotification.when = System.currentTimeMillis();
// defaultNotification.defaults |= Notification.DEFAULT_VIBRATE;
@@ -573,7 +581,12 @@ public class AutomationService extends Service implements OnInitListener
builder.setOnlyAlertOnce(true);
if(Settings.showIconWhenServiceIsRunning)
builder.setSmallIcon(R.drawable.ic_launcher);
{
if (BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
builder.setSmallIcon(R.drawable.crane);
else
builder.setSmallIcon(R.drawable.ic_launcher);
}
// builder.setContentText(textToDisplay);
// builder.setSmallIcon(icon);

View File

@@ -44,7 +44,11 @@ import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
@@ -70,6 +74,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -77,6 +82,8 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.DigestInputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
@@ -117,7 +124,7 @@ public class Miscellaneous extends Service
public static final String lineSeparator = System.getProperty("line.separator");
public static String downloadURL(String url, String username, String password)
public static String downloadURL(String url, String username, String password, String method)
{
HttpClient httpclient = new DefaultHttpClient();
StringBuilder responseBody = new StringBuilder();
@@ -145,6 +152,8 @@ public class Miscellaneous extends Service
connection.setDoOutput(true);
connection.setRequestProperty ("Authorization", "Basic " + encodedCredentials);
}
else if(method.equals(ActivityManageActionTriggerUrl.methodPost))
connection.setRequestMethod("POST");
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in = new BufferedReader (new InputStreamReader (content));
@@ -171,33 +180,42 @@ public class Miscellaneous extends Service
}
}
public static String downloadURLwithoutCertificateChecking(String url, String username, String password)
public static String downloadURLwithoutCertificateChecking(String url, String username, String password, String method)
{
// HttpClient httpclient = new DefaultHttpClient();
// StringBuilder responseBody = new StringBuilder();
boolean errorFound = false;
try
try
{
HttpParams params = new BasicHttpParams();
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpClient httpclient = new DefaultHttpClient(params);
httpclient = Actions.getInsecureSslClient(httpclient);
HttpPost httppost = new HttpPost(url);
HttpRequestBase httpRequest;
if(
method.equals(ActivityManageActionTriggerUrl.methodPost)
||
(username != null && password != null)
)
httpRequest = new HttpPost(url);
else
httpRequest = new HttpGet(url);
/*httpRequest = new HttpEntityEnclosingRequestBase()
{
@Override
public String getMethod()
{
return "GET";
}
};*/
// Add http simple authentication if specified
if(username != null && password != null)
{
String encodedCredentials = Base64.encodeToString(new String(username + ":" + password).getBytes(), Base64.DEFAULT);
// List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
httppost.addHeader("Authorization", "Basic " + encodedCredentials);
// nameValuePairs.add(new BasicNameValuePair("Authorization", "Basic " + encodedCredentials));
// httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
httpRequest.addHeader("Authorization", "Basic " + encodedCredentials);
}
HttpResponse response = httpclient.execute(httppost);
HttpResponse response = httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
if (entity != null)
{
@@ -208,8 +226,7 @@ public class Miscellaneous extends Service
catch(Exception e)
{
Miscellaneous.logEvent("e", "HTTP error", Log.getStackTraceString(e), 3);
errorFound = true;
return "httpError";
return "httpError";
}
// finally
// {
@@ -708,7 +725,7 @@ public class Miscellaneous extends Service
String notificationTitle = NotificationListener.getLastNotification().getTitle();
if (notificationTitle != null && notificationTitle.length() > 0)
source = source.replace("[notificationTitle]", notificationTitle);
source = source.replace("[notificationTitle]", escapeStringForUrl(notificationTitle));
else
{
source = source.replace("[notificationTitle]", "notificationTitle unknown");
@@ -729,7 +746,7 @@ public class Miscellaneous extends Service
String notificationText = NotificationListener.getLastNotification().getText();
if (notificationText != null && notificationText.length() > 0)
source = source.replace("[notificationText]", notificationText);
source = source.replace("[notificationText]", escapeStringForUrl(notificationText));
else
{
source = source.replace("[notificationText]", "notificationText unknown");
@@ -760,7 +777,7 @@ public class Miscellaneous extends Service
else
replacement = "unknownVariable";
source = source.substring(0, pos1) + replacement + source.substring(pos2 +1);
source = source.substring(0, pos1) + escapeStringForUrl(replacement) + source.substring(pos2 +1);
}
// Miscellaneous.logEvent("i", "URL after replace", source);
@@ -1164,7 +1181,12 @@ public class Miscellaneous extends Service
builder.setOnlyAlertOnce(true);
if(Settings.showIconWhenServiceIsRunning && notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.ic_launcher);
{
if(BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
builder.setSmallIcon(R.drawable.crane);
else
builder.setSmallIcon(R.drawable.ic_launcher);
}
else if(!notificationChannelId.equals(AutomationService.NOTIFICATION_CHANNEL_ID_SERVICE))
builder.setSmallIcon(R.drawable.info);
@@ -2034,4 +2056,28 @@ public class Miscellaneous extends Service
//startActivity(refresh);
}
}
public static String escapeStringForUrl(String input)
{
String output;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
try
{
output = URLEncoder.encode(input, String.valueOf(StandardCharsets.UTF_8));
}
catch (UnsupportedEncodingException e)
{
Miscellaneous.logEvent("e", "URLEncoder", "Error encoding string for URL. Leaving as it is. Error details: " + Log.getStackTraceString(e), 3);
output = input;
}
}
else
{
output = Uri.encode(input);
}
return output;
}
}

View File

@@ -0,0 +1,51 @@
package com.jens.automation2;
import android.accessibilityservice.AccessibilityService;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
public class MyAccessibilityService extends AccessibilityService
{
static MyAccessibilityService instance;
public static MyAccessibilityService getInstance()
{
if(instance == null)
{
instance = new MyAccessibilityService();
}
return instance;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent)
{
}
@Override
public void onInterrupt()
{
}
@Override
public void onCreate()
{
super.onCreate();
instance = this;
}
@Override
protected void onServiceConnected()
{
super.onServiceConnected();
Miscellaneous.logEvent("i", "Accessibility service", "Service started.", 4);
}
}

View File

@@ -79,7 +79,7 @@ public class News
if (!(new File(filePath)).exists() || Settings.lastNewsPolltime == Settings.default_lastNewsPolltime || now.getTimeInMillis() >= Settings.lastNewsPolltime + (long)(Settings.newsDisplayForXDays * 24 * 60 * 60 * 1000))
{
String newsUrl = "https://server47.de/automation/appNews.php";
newsContent = Miscellaneous.downloadURL(newsUrl, null, null);
newsContent = Miscellaneous.downloadURL(newsUrl, null, null, ActivityManageActionTriggerUrl.methodGet);
// Cache content to local storage
if(Miscellaneous.writeStringToFile(filePath, newsContent))

View File

@@ -145,7 +145,8 @@ public class ReceiverCoordinator
}
// startPhoneStateListener
PhoneStatusListener.startPhoneStatusListener(AutomationService.getInstance()); // also used to mute anouncements during calls
if(!BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
PhoneStatusListener.startPhoneStatusListener(AutomationService.getInstance()); // also used to mute anouncements during calls
// startConnectivityReceiver
ConnectivityReceiver.startConnectivityReceiver(AutomationService.getInstance());
@@ -391,11 +392,11 @@ public class ReceiverCoordinator
}
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.headsetPlugged))
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.headsetPlugged))
{
if(!HeadphoneJackListener.isHeadphoneJackListenerActive())
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting HeadphoneJackListener because used in a new/changed rule.", 4);
Miscellaneous.logEvent("i", "HeadphoneJackListener", "Starting HeadphoneJackListener because used in a new/changed rule.", 4);
if(HeadphoneJackListener.getInstance().haveAllPermission())
HeadphoneJackListener.getInstance().startListener(AutomationService.getInstance());
}
@@ -404,7 +405,7 @@ public class ReceiverCoordinator
{
if(HeadphoneJackListener.isHeadphoneJackListenerActive())
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down HeadphoneJackListener because not used in any rule.", 4);
Miscellaneous.logEvent("i", "HeadphoneJackListener", "Shutting down HeadphoneJackListener because not used in any rule.", 4);
HeadphoneJackListener.getInstance().stopListener(AutomationService.getInstance());
}
}

View File

@@ -803,13 +803,29 @@ public class Trigger
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Wifi name specified, checking that.", this.getParentRule().getName()), 4);
if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2()) && !(Miscellaneous.isRegularExpression(this.getTriggerParameter2()) && WifiBroadcastReceiver.getLastWifiSsid().matches(this.getTriggerParameter2())))
if(WifiBroadcastReceiver.lastConnectedState) //when connected
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()),this.getParentRule().getName()), 3);
return false;
if (!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2()) && !(Miscellaneous.isRegularExpression(this.getTriggerParameter2()) && WifiBroadcastReceiver.getLastWifiSsid().matches(this.getTriggerParameter2())))
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), this.getParentRule().getName()), 3);
return false;
}
else
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Wifi name matches. Rule will apply.", this.getParentRule().getName()), 4);
}
else
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Wifi name matches. Rule will apply.", this.getParentRule().getName()), 4);
{
if (
!Settings.serviceStartDone
||
(!WifiBroadcastReceiver.getLastWifiSsidReal().equals(this.getTriggerParameter2()) && !(Miscellaneous.isRegularExpression(this.getTriggerParameter2()) && WifiBroadcastReceiver.getLastWifiSsidReal().matches(this.getTriggerParameter2()))))
{
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsidReal()), this.getParentRule().getName()), 3);
return false;
}
else
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Wifi name matches. Rule will apply.", this.getParentRule().getName()), 4);
}
}
else
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("No wifi name specified, any will do.", this.getParentRule().getName()), 4);

View File

@@ -217,7 +217,7 @@ public class XmlFileInterface
}
serializer.endTag(null, "ProfileCollection");
serializer.startTag(null, "RuleCollection");
for(int i=0; i<Rule.getRuleCollection().size(); i++)
{
@@ -1286,20 +1286,24 @@ public class XmlFileInterface
else
newTag = tag.replace("/", Action.intentPairSeparator);
String[] newTagPieces = newTag.split(";");
String[] newTagPieces = new String[0];
if(newTag.contains(Action.actionParameter2Split))
newTagPieces = newTag.split(Action.actionParameter2Split);
else
newTag.split(";");
if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeparator)))
{
newTag = Actions.dummyPackageString + ";" + newTag;
newTagPieces = newTag.split(";");
newTag = Actions.dummyPackageString + Action.actionParameter2Split + newTag;
newTagPieces = newTag.split(Action.actionParameter2Split);
}
if(newTagPieces.length < 3)
newTag += ";" + ActivityManageActionStartActivity.startByActivityString;
newTag += Action.actionParameter2Split + ActivityManageActionStartActivity.startByActivityString;
else if(newTagPieces.length >= 3)
{
if(newTagPieces[2].contains(Action.intentPairSeparator))
newTag = newTagPieces[0] + ";" + newTagPieces[1] + ";" + ActivityManageActionStartActivity.startByActivityString + ";" + newTagPieces[2];
newTag = newTagPieces[0] + Action.actionParameter2Split + newTagPieces[1] + Action.actionParameter2Split + ActivityManageActionStartActivity.startByActivityString + Action.actionParameter2Split + newTagPieces[2];
}
newAction.setParameter2(newTag);

View File

@@ -11,6 +11,7 @@ import android.util.Log;
import com.jens.automation2.ActivityMainScreen;
import com.jens.automation2.AutomationService;
import com.jens.automation2.BuildConfig;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.PointOfInterest;
import com.jens.automation2.R;
@@ -232,6 +233,7 @@ public class LocationProvider
public void startLocationService()
{
// startPhoneStateListener
if(!BuildConfig.FLAVOR.equals(AutomationService.flavor_name_googleplay))
PhoneStatusListener.startPhoneStatusListener(parentService); // also used to mute anouncements during calls
// startConnectivityReceiver
@@ -400,12 +402,12 @@ public class LocationProvider
Miscellaneous.logEvent("i", "LocationProvider", this.getParentService().getResources().getString(R.string.applyingSettingsAndRules), 3);
// *********** SETTING CHANGES ***********
if(Settings.useWifiForPositioning && !WifiBroadcastReceiver.isWifiListenerActive())
if(Settings.useWifiForPositioning && !WifiBroadcastReceiver.isWifiListenerActive() || Rule.isAnyRuleUsing(Trigger_Enum.wifiConnection))
{
Miscellaneous.logEvent("i", "LocationProvider", "Starting WifiReceiver because settings now allow to.", 4);
WifiBroadcastReceiver.startWifiReceiver(this);
}
else if(!Settings.useWifiForPositioning && WifiBroadcastReceiver.isWifiListenerActive())
else if(!Settings.useWifiForPositioning && WifiBroadcastReceiver.isWifiListenerActive() && !Rule.isAnyRuleUsing(Trigger_Enum.wifiConnection))
{
Miscellaneous.logEvent("i", "LocationProvider", "Shutting down WifiReceiver because settings forbid to.", 4);
WifiBroadcastReceiver.stopWifiReceiver();

View File

@@ -25,12 +25,20 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
public static LocationProvider parentLocationProvider;
public static Boolean wasConnected = false;
protected static String lastWifiSsid = "";
protected static String lastWifiSsidReal = "";
public static boolean lastConnectedState = false;
protected static boolean mayCellLocationChangedReceiverBeActivatedFromWifiPointOfView = true;
protected static WifiBroadcastReceiver wifiBrInstance;
protected static IntentFilter wifiListenerIntentFilter;
protected static boolean wifiListenerActive=false;
final static String unknownSsidName = "<unknown ssid>";
public static String getLastWifiSsidReal()
{
return lastWifiSsidReal;
}
public static String getLastWifiSsid()
{
return lastWifiSsid;
@@ -42,7 +50,11 @@ public class WifiBroadcastReceiver extends BroadcastReceiver
newWifiSsid = newWifiSsid.substring(1, newWifiSsid.length()-1);
if(newWifiSsid.length() > 0)
{
if(newWifiSsid.equals(unknownSsidName))
WifiBroadcastReceiver.lastWifiSsidReal = lastWifiSsid;
WifiBroadcastReceiver.lastWifiSsid = newWifiSsid;
}
}
public static boolean isWifiListenerActive()

View File

@@ -32,21 +32,21 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
if(!batteryReceiverActive)
{
BatteryReceiver.automationServiceRef = automationServiceRef;
if(batteryInfoReceiverInstance == null)
batteryInfoReceiverInstance = new BatteryReceiver();
if(batteryIntentFilter == null)
{
batteryIntentFilter = new IntentFilter();
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_LOW);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
// batteryIntentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
}
batteryStatus = automationServiceRef.registerReceiver(batteryInfoReceiverInstance, batteryIntentFilter);
batteryReceiverActive = true;
}
}
@@ -59,16 +59,16 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
automationServiceRef.unregisterReceiver(batteryInfoReceiverInstance);
batteryInfoReceiverInstance = null;
}
batteryReceiverActive = false;
}
}
public static boolean isBatteryReceiverActive()
{
return batteryReceiverActive;
}
public static boolean isUsbHostConnected()
{
return usbHostConnected;
@@ -80,7 +80,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
}
private static int currentChargingState = 0; //0=unknown, 1=no, 2=yes
public static int getCurrentChargingState()
{
return currentChargingState;
@@ -90,11 +90,11 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
public void onReceive(Context context, Intent intent)
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Received event " + intent.getAction(), 5);
if (intent == null)
return;
if (context == null)
return;
return;
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW))
{
@@ -105,12 +105,12 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
try
{
batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
// int scale = -1;
// int voltage = -1;
// int temp = -1;
// scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
// temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
// voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
// int scale = -1;
// int voltage = -1;
// int temp = -1;
// scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
// temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
// voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
Log.i("Battery", "Level: " + String.valueOf(batteryLevel));
this.actionBatteryLevel(context);
@@ -121,7 +121,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
switch(statusPlugged)
{
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);
this.actionCharging(context);
break;
@@ -134,10 +134,11 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
{
case BatteryManager.BATTERY_STATUS_CHARGING:
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);
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
this.actionDischarging(context);
break;
}
@@ -148,7 +149,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
}
}
}
public static int isDeviceCharging(Context context)
{
switch(currentChargingState)
@@ -163,10 +164,10 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is charging.", 3);
break;
}
return currentChargingState;
}
private void actionCharging(Context context)
{
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.
@@ -183,7 +184,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
}
}
}
private void actionBatteryLevel(Context context)
{
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery level has changed.", 3);
@@ -195,7 +196,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
private void actionDischarging(Context context)
{
if(currentChargingState != BatteryManager.BATTERY_STATUS_UNKNOWN) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
@@ -210,17 +211,17 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
this.actionUsbDisconnected(context);
}
}
private void actionUsbConnected(Context context)
{
// Event usbConnected
// Miscellaneous.logEvent("i", "BatteryReceiver", "BATTERY_PLUGGED_USB");
if(!usbHostConnected)
{
usbHostConnected = true;
@@ -234,15 +235,15 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList
if(oneRule.getsGreenLight(context))
oneRule.activate(automationServiceRef, false);
}
this.actionCharging(context);
}
}
private void actionUsbDisconnected(Context context)
{
// Event usbDisConnected
if(usbHostConnected)
{
usbHostConnected = false;

View File

@@ -94,20 +94,21 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
@Override
public void onReceive(Context context, Intent intent)
{
// Miscellaneous.logEvent("i", "BluetoothReceiver", "Bluetooth event.", 4);
String action = intent.getAction();
Miscellaneous.logEvent("i", "BluetoothReceiver", "Bluetooth event: " + action, 5);
BluetoothDevice bluetoothDevice = null;
if(action.equals(BluetoothDevice.ACTION_ACL_CONNECTED) | action.equals("android.bluetooth.device.action.ACL_CONNECTED"))
{
if(action.equals(BluetoothDevice.ACTION_ACL_CONNECTED) || action.equals("android.bluetooth.device.action.ACL_CONNECTED"))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
lastAffectedDevice = bluetoothDevice;
lastAction = action;
connectedDevices.add(bluetoothDevice);
Miscellaneous.logEvent("i", "BluetoothReceiver", String.format(context.getResources().getString(R.string.bluetoothConnectionTo), bluetoothDevice.getName()), 3);
}
else if(action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED) | action.equals(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED) | action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECTED") | action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECT_REQUESTED"))
else if(action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED) || action.equals(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED) || action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECTED") || action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECT_REQUESTED"))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
lastAffectedDevice = bluetoothDevice;
@@ -115,7 +116,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi
connectedDevices.remove(bluetoothDevice);
Miscellaneous.logEvent("i", "BluetoothReceiver", String.format(context.getResources().getString(R.string.bluetoothDisconnectFrom), bluetoothDevice.getName()), 3);
}
else if(action.equals(BluetoothDevice.ACTION_FOUND) | action.equals("android.bluetooth.device.ACTION_FOUND"))
else if(action.equals(BluetoothDevice.ACTION_FOUND) || action.equals("android.bluetooth.device.ACTION_FOUND"))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
lastAffectedDevice = bluetoothDevice;

View File

@@ -52,9 +52,13 @@ public class BroadcastListener extends android.content.BroadcastReceiver impleme
{
broadcastsCollection.add(new EventOccurrence(Calendar.getInstance(), intent.getAction()));
for(String key : intent.getExtras().keySet())
Miscellaneous.logEvent("i", "Broadcast received", "Broadcast " + intent.getAction() + " received.", 4);
if(intent.getExtras() != null && intent.getExtras().size() > 0)
{
Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
for (String key : intent.getExtras().keySet())
{
Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
}
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.broadcastReceived);

View File

@@ -11,6 +11,7 @@ import android.util.Log;
import androidx.annotation.RequiresApi;
import com.jens.automation2.AutomationService;
import com.jens.automation2.BuildConfig;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.TimeFrame;
@@ -243,7 +244,12 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis
}
Intent alarmIntent = new Intent(automationServiceRef, DateTimeListener.class);
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if(Miscellaneous.getAnyContext().getApplicationContext().getApplicationInfo().targetSdkVersion >= 31)
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
else
alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate.time.getTimeInMillis(), alarmPendingIntent);
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm:ss");

View File

@@ -20,7 +20,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati
private static boolean headsetConnected = false;
private static int headphoneType = -1;
protected static boolean headphoneJackListenerActive=false;
protected static boolean headphoneJackListenerActive = false;
protected static IntentFilter headphoneJackListenerIntentFilter = null;
protected static HeadphoneJackListener instance;
@@ -108,7 +108,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error starting HeadsetJackListener: " + Log.getStackTraceString(ex), 3);
Miscellaneous.logEvent("e", "HeadsetJackListener", "Error starting HeadsetJackListener: " + Log.getStackTraceString(ex), 3);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -113,6 +113,7 @@
android:text="@string/startAppStartType" />
<RadioGroup
android:id="@+id/rgAppStartupType"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -135,6 +136,12 @@
android:layout_height="wrap_content"
android:text="@string/startAppByStartService" />
<RadioButton
android:id="@+id/rbStartAppByForegroundService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/startAppByStartForegroundService" />
</RadioGroup>
</TableRow>
@@ -187,6 +194,25 @@
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/className" />
<EditText
android:id="@+id/etClassName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">

View File

@@ -90,6 +90,34 @@
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/method"
android:layout_marginTop="@dimen/fab_margin"
android:textStyle="bold" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rbTriggerUrlMethodGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/methodGet" />
<RadioButton
android:id="@+id/rbTriggerUrlMethodPost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/default_margin"
android:text="@string/methodPost" />
</RadioGroup>
<ListView
android:id="@+id/lvTriggerUrlPostParameters"
android:layout_width="match_parent"

View File

@@ -103,6 +103,14 @@
</TableLayout>
<TextView
android:id="@+id/tvWifiTriggerDisconnectionHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/default_margin"
android:textColor="@color/red"
android:text="@string/wifiTriggerDisconnectionHint" />
<Button
android:id="@+id/bTriggerWifiSave"
android:layout_marginTop="@dimen/default_margin"

View File

@@ -66,6 +66,12 @@
</LinearLayout>
<TextView
android:id="@+id/tvRestrictionPermissionsNotice"
android:textColor="@color/red"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -799,4 +799,14 @@
<string name="intentParametersHint">Wenn Sie einen Parameter angeben möchten, müssen Sie auch auf \"Intent-Paar hinzufügen\" klicken. Andernfalls werden Ihre Änderungen nicht gespeichert.</string>
<string name="languagePolish">Polnisch</string>
<string name="languageChineseChina">Chinesisch (China)</string>
<string name="wifiTriggerDisconnectionHint">Dieser Auslöser ist gültig, wenn Sie gerade die Verbindung zu dem oben angegebenen WLAN getrennt haben ODER während der Dienst noch gestartet wird und wenn Sie mit keinem WLAN verbunden sind. Wenn Sie möchten, dass der Auslöser nur ausgelöst wird, wenn Sie die Verbindung zu einem bestimmten WLAN explizit trennen, fügen Sie einen weiteren Auslöser hinzu: \"Der Dienst wird nicht gestartet\".</string>
<string name="className">Klassenname</string>
<string name="startAppByStartForegroundService">per startForegroundService()</string>
<string name="method">Methode</string>
<string name="takeScreenshot">Screenshot erstellen</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">An den Barrierefreiheitsdienst anbinden</string>
<string name="bindAccessibilityService">An den Barrierefreiheitsdienst anbinden</string>
<string name="accessibilityApiPermissionHint">Nachdem Sie auf OK geklickt haben, werden Sie zu einem Systemdialog weitergeleitet. Bitte wählen Sie dort Automatisierung aus und erlauben Sie die Barrierefreiheits-API.</string>
<string name="accessibility_service_explanation">Erforderlich für bestimmte Aktionen.</string>
<string name="noticeRestrictedPermissions">Wenn Sie eine der folgenden Berechtigungen nicht erteilen und eine Systemmeldung wie \"Eingeschränkte Berechtigung\" erhalten, müssen Sie zuerst zu den Android-Einstellungen und dann zu den Anwendungen gehen und Automatisierung auswählen. Nun sollten sich 3 Punkte in der oberen rechten Ecke befinden. Klicken Sie auf \"Eingeschränkte Einstellungen zulassen\". Danach sollte die erforderliche Erlaubnis erteilt werden können. Dies sollte nur für die APK-Version der App gelten, nicht für die von F-Droid oder dem Play Store.</string>
</resources>

View File

@@ -43,7 +43,7 @@
<string name="enterAname">Inserte un nombre.</string>
<string name="username">Nombre de usuario</string>
<string name="ok">Ok</string>
<string name="continueText">continuar</string>
<string name="continueText">Continuar</string>
<string name="rule">Regla</string>
<string name="android.permission.SEND_SMS">Enviar mensajes SMS</string>
<string name="android.permission.READ_CONTACTS">Leer directorio</string>
@@ -197,7 +197,7 @@
<string name="android.permission.RECORD_AUDIO">Grabar audio</string>
<string name="android.permission.PROCESS_OUTGOING_CALLS">Detectar llamadas salientes</string>
<string name="android.permission.READ_PHONE_STATE">Detectar el estado del dispositivo</string>
<string name="android.permission.READ_EXTERNAL_STORAGE">Leer la almacenamiento</string>
<string name="android.permission.READ_EXTERNAL_STORAGE">Leer el almacenamiento</string>
<string name="android.permission.WRITE_EXTERNAL_STORAGE">Escribir en el almacenamiento</string>
<string name="android.permission.WRITE_SETTINGS">Modificar la configuración del dispositivo</string>
<string name="android.permission.BATTERY_STATS">Determinar el estado de la bateria</string>
@@ -798,4 +798,14 @@
<string name="intentParametersHint">Si desea especificar un parámetro, también debe hacer clic en \"Agregar par de intención\". De lo contrario, los cambios no se guardarán.</string>
<string name="languagePolish">Polaco</string>
<string name="languageChineseChina">Chino (China)</string>
<string name="wifiTriggerDisconnectionHint">Este activador será válido si acabas de desconectarte del wifi especificado anteriormente O mientras el servicio aún se está iniciando y si no estás conectado a ningún wifi. Si desea que el activador se active solo cuando se desconecte explícitamente de una determinada red WiFi, agregue otro activador \"el servicio no se está iniciando\".</string>
<string name="className">Nombre de la clase</string>
<string name="startAppByStartForegroundService">a través de startForegroundService((</string>
<string name="method">Método</string>
<string name="takeScreenshot">Tomar captura de pantalla</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Enlazar al servicio de accesibilidad</string>
<string name="bindAccessibilityService">Enlazar al servicio de accesibilidad</string>
<string name="accessibilityApiPermissionHint">Después de hacer clic en Aceptar, se le enviará a un cuadro de diálogo del sistema. Seleccione Automatización allí y permita Permitir API de accesibilidad.</string>
<string name="accessibility_service_explanation">Requerido para ciertas acciones.</string>
<string name="noticeRestrictedPermissions">Si no le otorga a uno el siguiente permiso y un mensaje del sistema como \"Ajuste restringido\", primero debe ir a la configuración de Android, luego a las aplicaciones, elija Automatización. Ahora debería haber 3 puntos en la esquina superior derecha. Haga clic en \"Permitir configuraciones restringidas\". Después de eso, el permiso necesario debería poder otorgarse. Esto solo debería aplicarse a la versión APK de la aplicación, no a las de F-Droid o Play Store.</string>
</resources>

View File

@@ -798,4 +798,14 @@
<string name="intentParametersHint">Si vous souhaitez spécifier un paramètre, vous devez également cliquer sur « Ajouter une paire d\'intentions ». Sinon, vos modifications ne seront pas enregistrées.</string>
<string name="languagePolish">Polonais</string>
<string name="languageChineseChina">Chinois (Chine)</string>
<string name="wifiTriggerDisconnectionHint">Ce déclencheur sera valide si vous venez de vous déconnecter du wifi spécifié ci-dessus OU alors que le service est encore en cours de démarrage et si vous n\'êtes connecté à aucun wifi. Si vous souhaitez que le déclencheur ne se déclenche que lorsque vous vous déconnectez explicitement d\'un certain wifi, ajoutez un autre déclencheur « le service ne démarre pas ».</string>
<string name="className">Nom de la classe</string>
<string name="startAppByStartForegroundService">par startForegroundService()</string>
<string name="method">Méthode</string>
<string name="takeScreenshot">Prendre une capture d\'écran</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Se lier au service d\'accessibilité</string>
<string name="bindAccessibilityService">Se lier au service d\'accessibilité</string>
<string name="accessibilityApiPermissionHint">Après avoir cliqué sur OK, vous serez redirigé vers une boîte de dialogue système. Sélectionnez Automatisation et autorisez l\'option Autoriser l\'API d\'accessibilité.</string>
<string name="accessibility_service_explanation">Obligatoire pour certaines actions.</string>
<string name="noticeRestrictedPermissions">Si vous ne parvenez pas à accorder à l\'un d\'entre eux l\'autorisation suivante et un message système tel que « Autorisation restreinte », vous devez d\'abord accéder aux paramètres Android, puis aux applications, puis choisir Automatisation. Maintenant, il devrait y avoir 3 points dans le coin supérieur droit. Cliquez sur « Autoriser les paramètres restreints ». Après cela, l\'autorisation nécessaire devrait pouvoir être accordée. Cela ne devrait s\'appliquer qu\'à la version APK de l\'application, pas à celles de F-Droid ou du Play Store.</string>
</resources>

View File

@@ -799,4 +799,14 @@
<string name="intentParametersHint">Se si desidera specificare un parametro è necessario fare clic anche su \"Aggiungi coppia intento\". In caso contrario, le modifiche non verranno salvate.</string>
<string name="languagePolish">Polacco</string>
<string name="languageChineseChina">Cinese (Cina)</string>
<string name="wifiTriggerDisconnectionHint">Questo trigger sarà valido se ti sei appena disconnesso dal Wi-Fi specificato sopra OPPURE mentre il servizio è ancora in fase di avvio e se non sei connesso a nessuna rete Wi-Fi. Se vuoi che il trigger si attivi solo quando ti stai disconnettendo esplicitamente da una determinata rete Wi-Fi, aggiungi un altro trigger \"il servizio non si avvia\".</string>
<string name="className">Nome della classe</string>
<string name="startAppByStartForegroundService">di startForegroundService()</string>
<string name="method">Metodo</string>
<string name="takeScreenshot">Fai uno screenshot</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Associare al servizio di accessibilità</string>
<string name="bindAccessibilityService">Associare al servizio di accessibilità</string>
<string name="accessibilityApiPermissionHint">Dopo aver fatto clic su OK, verrà visualizzata una finestra di dialogo di sistema. Seleziona Automazione e consenti Consenti API di accessibilità.</string>
<string name="accessibility_service_explanation">Obbligatorio per determinate azioni.</string>
<string name="noticeRestrictedPermissions">Se non riesci a concedere una delle seguenti autorizzazioni e un messaggio di sistema come \"Autorizzazione limitata\", devi prima andare alle impostazioni di Android, quindi alle applicazioni, scegli Automazione. Ora dovrebbero esserci 3 punti nell\'angolo in alto a destra. Fai clic su \"Consenti impostazioni limitate\". Dopodiché dovrebbe essere concessa l\'autorizzazione necessaria. Questo dovrebbe valere solo per la versione APK dell\'app, non per quelle di F-Droid o Play Store.</string>
</resources>

View File

@@ -797,5 +797,15 @@
<string name="intentParametersHint">Als u een parameter wilt opgeven, moet u ook op \"Intentiepaar toevoegen\" klikken. Anders worden uw wijzigingen niet opgeslagen.</string>
<string name="languagePolish">Pools</string>
<string name="languageChineseChina">Chinees (China)</string>
<string name="wifiTriggerDisconnectionHint">Deze trigger is geldig als je net de verbinding met de hierboven gespecificeerde wifi hebt verbroken OF terwijl de service nog aan het starten is en als je niet verbonden bent met wifi. Als je wilt dat de trigger alleen wordt geactiveerd wanneer je expliciet de verbinding met een bepaalde wifi verbreekt, voeg dan nog een trigger toe \"service start niet\".</string>
<string name="className">Naam van de klasse</string>
<string name="startAppByStartForegroundService">door startForegroundService()</string>
<string name="method">Methode</string>
<string name="takeScreenshot">Screenshot maken</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Binden aan toegankelijkheidsservice</string>
<string name="bindAccessibilityService">Binden aan toegankelijkheidsservice</string>
<string name="accessibilityApiPermissionHint">Nadat u op OK hebt geklikt, wordt u naar een systeemdialoogvenster gestuurd. Selecteer daar Automatisering en sta Toegankelijkheids-API toestaan toe.</string>
<string name="accessibility_service_explanation">Vereist voor bepaalde acties.</string>
<string name="noticeRestrictedPermissions">Als u er niet in slaagt om een van de volgende machtigingen en een systeembericht zoals \"Beperkte toestemming\" te verlenen, moet u eerst naar Android-instellingen gaan en vervolgens naar toepassingen en Automatisering kiezen. Nu zouden er 3 stippen in de rechterbovenhoek moeten zijn. Klik op \"Beperkte instellingen toestaan\". Daarna moet de benodigde toestemming aanvaardbaar zijn. Dit zou alleen van toepassing moeten zijn op de APK-versie van de app, niet die van F-Droid of Play Store.</string>
</resources>

View File

@@ -896,4 +896,14 @@
<string name="languageFrench">Francuski</string>
<string name="languagePolish">Polski</string>
<string name="languageChineseChina">Chiński (Chiny)</string>
<string name="wifiTriggerDisconnectionHint">Ten wyzwalacz będzie prawidłowy, jeśli właśnie rozłączyłeś się z Wi-Fi określonym powyżej LUB gdy usługa jest nadal uruchomiona i jeśli nie masz połączenia z żadną siecią Wi-Fi. Jeśli chcesz, aby wyzwalacz uruchamiał się tylko wtedy, gdy jawnie rozłączasz się z określoną siecią Wi-Fi, dodaj kolejny wyzwalacz \"usługa nie uruchamia się\".</string>
<string name="className">nazwa klasy</string>
<string name="startAppByStartForegroundService">przez startForegroundService()</string>
<string name="method">Metoda</string>
<string name="takeScreenshot">Zrób zrzut ekranu</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Powiąż z usługą ułatwień dostępu</string>
<string name="bindAccessibilityService">Powiąż z usługą ułatwień dostępu</string>
<string name="accessibilityApiPermissionHint">Po kliknięciu OK zostaniesz przekierowany do systemowego okna dialogowego. Wybierz tam Automatyzację i zezwól na Zezwalaj na interfejs API ułatwień dostępu.</string>
<string name="accessibility_service_explanation">Wymagane w przypadku niektórych działań.</string>
<string name="noticeRestrictedPermissions">Jeśli nie uda Ci się przyznać następującego uprawnienia i komunikatu systemowego, takiego jak \"Ograniczone uprawnienia\", musisz najpierw przejść do ustawień Androida, a następnie aplikacji, wybrać Automatyzacja. Teraz w prawym górnym rogu powinny znajdować się 3 kropki. Kliknij \"Zezwól na ustawienia z ograniczeniami\". Następnie powinno być możliwe udzielenie niezbędnego pozwolenia. Powinno to dotyczyć tylko wersji APK aplikacji, a nie tych z F-Droid lub Sklepu Play.</string>
</resources>

View File

@@ -856,4 +856,14 @@
<string name="intentParametersHint">Если вы хотите указать параметр, вам также нужно нажать «Добавить пару намерений». В противном случае ваши изменения не будут сохранены.</string>
<string name="languagePolish">Польский</string>
<string name="languageChineseChina">Китайский (Китай)</string>
<string name="wifiTriggerDisconnectionHint">Этот триггер будет действителен, если вы только что отключились от Wi-Fi, указанного выше, ИЛИ во время запуска службы и если вы не подключены ни к одному Wi-Fi. Если вы хотите, чтобы триггер срабатывал только тогда, когда вы явно отключаетесь от определенного Wi-Fi, добавьте еще один триггер «сервис не запускается».</string>
<string name="className">Имя класса</string>
<string name="startAppByStartForegroundService">no startForegroundService()</string>
<string name="method">Метод</string>
<string name="takeScreenshot">Сделать снимок экрана</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Привязка к службе специальных возможностей</string>
<string name="bindAccessibilityService">Привязка к службе специальных возможностей</string>
<string name="accessibilityApiPermissionHint">После нажатия кнопки «ОК» вы попадете в системное диалоговое окно. Выберите там «Автоматизация» и разрешите «Разрешить API специальных возможностей».</string>
<string name="accessibility_service_explanation">Required for certain actions.</string>
<string name="noticeRestrictedPermissions">Если вы не можете предоставить одно из следующих разрешений и системное сообщение типа «Ограниченное разрешение», вам нужно сначала перейти в настройки Android, затем в приложения, выбрать «Автоматизация». Теперь в правом верхнем углу должно быть 3 точки. Нажмите «Разрешить ограниченные настройки». После этого необходимо получить необходимое разрешение. Это должно относиться только к APK-версии приложения, а не к версии из F-Droid или Play Store.</string>
</resources>

View File

@@ -797,4 +797,14 @@
<string name="languagePolish">波兰语</string>
<string name="languageChineseChina">中文(中国)</string>
<string name="intentParametersHint">若要指定一个参数,还必须点击“添加 Intent 对”,否则更改不会保存。</string>
<string name="wifiTriggerDisconnectionHint">如果您刚刚断开了与上面指定的 wifi 的连接,或者在服务仍在启动并且您没有连接到任何 wifi则此触发器将有效。 如果您希望触发器仅在您明确断开与某个 wifi 的连接时触发,请添加另一个触发器\"服务未启动\"。</string>
<string name="className">类名</string>
<string name="startAppByStartForegroundService">来自 startForegroundService()</string>
<string name="method">方法</string>
<string name="takeScreenshot">截屏</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">绑定到辅助功能服务</string>
<string name="bindAccessibilityService">绑定到辅助功能服务</string>
<string name="accessibilityApiPermissionHint">单击\"确定\"后,您将被发送到系统对话框。请在此处选择\"自动化\",并允许\"允许辅助功能 API\"。</string>
<string name="accessibility_service_explanation">对于某些操作是必需的。</string>
<string name="noticeRestrictedPermissions">如果您未能授予以下权限和\"受限权限\"之类的系统消息,则需要先转到 Android 设置,然后转到应用程序,选择自动化。现在右上角应该有 3 个点。单击\"允许受限设置\"。之后,应该可以授予必要的权限。这应该仅适用于应用的 APK 版本,而不适用于 F-Droid 或 Play 商店中的版本。</string>
</resources>

View File

@@ -422,7 +422,7 @@
<string name="noDataChangedReadingAnyway">It appears no data change has been saved. However there may have been changes in memory that need to be rolled back. Rereading file.</string>
<string name="bluetoothConnection">Bluetooth connection</string>
<string name="bluetoothConnectionTo">Bluetooth connection to %1$s</string>
<string name="bluetoothDisconnectFrom">Bluetooth connection to %1$s torn</string>
<string name="bluetoothDisconnectFrom">Bluetooth connection from %1$s torn</string>
<string name="bluetoothDeviceInRange">Bluetooth device %1$s in range.</string>
<string name="bluetoothDeviceOutOfRange">Bluetooth device %1$s out of range.</string>
<string name="anyDevice">any device</string>
@@ -882,8 +882,20 @@
<string name="wifiMonitoringAlsoRequiresThis">This permission is also required if the trigger is using the current wifi connection.</string>
<string name="copyTextToClipboard">Copy text to clipboard</string>
<string name="textToCopy">Text to copy</string>
<string name="android.permission.SYSTEM_ALERT_WINDOW">Draw over other apps</string>
<string name="overlayPermissionHint">After clicking OK you\'ll be sent to a system dialog. Please select Automation there and allow "draw over other apps".</string>
<string name="android.permission.SYSTEM_ALERT_WINDOW">Display over other apps</string>
<string name="overlayPermissionHint">After clicking OK you\'ll be sent to a system dialog. Please select Automation there and allow "Display over other apps".</string>
<string name="variablesOnlyForTypes">Variables are only available for parameter types String and URI</string>
<string name="intentParametersHint">If you want to specify a parameter you also have to click \"Add intent pair\". Otherwise your changes will not be saved.</string>
<string name="wifiTriggerDisconnectionHint">This trigger will be valid if you just disconnected from the wifi specified above OR while the service is still starting and if you\'re not connected to any wifi. If you want the trigger to fire only when you\'re explicitly disconnecting from a certain wifi, add another trigger \"service is not starting\".</string>
<string name="className">Class full name</string>
<string name="startAppByStartForegroundService">by startForegroundService()</string>
<string name="method">Method</string>
<string name="methodGet" translatable="false">GET</string>
<string name="methodPost" translatable="false">POST</string>
<string name="takeScreenshot">Take screenshot</string>
<string name="android.permission.BIND_ACCESSIBILITY_SERVICE">Bind to accessibility service</string>
<string name="bindAccessibilityService">Bind to accessibility service</string>
<string name="accessibilityApiPermissionHint">After clicking OK you\'ll be sent to a system dialog. Please select Automation there and allow "Allow accessibility API".</string>
<string name="accessibility_service_explanation">Required for certain actions.</string>
<string name="noticeRestrictedPermissions">If you fail to grant one the following permission and a system message like \"Restricted permission\" you need to go to Android settings first, then applications, choose Automation. Now there should be 3 dots in the upper right corner. Click \"Allow restricted settings\". After that the necessary permission should be grantable. This should only apply to the APK version of the app, not the ones from F-Droid or Play Store.</string>
</resources>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagDefault"
android:accessibilityFeedbackType="feedbackSpoken"
android:canPerformGestures="false"
android:canRequestFilterKeyEvents="false"
android:canRequestFingerprintGestures="false"
android:canRetrieveWindowContent="false"
android:canTakeScreenshot="true"
android:notificationTimeout="0"
android:description="@string/accessibility_service_explanation" />

View File

@@ -0,0 +1,2 @@
* Geändert: Symbol in Play store Version
* Geändert: targetSdk mußte in Google Play Version auf 32 erhöht werden. Falls das Fehler verursacht, denken Sie darüber nach zur F-Droid oder APK version zu wechseln.

View File

@@ -0,0 +1,6 @@
* Behoben: Overlay-Berechtigung für Start-Telefonanruf-Aktion hinzugefügt
* Behoben: Der Auslöser "Akku wird geladen" wurde nur einmal ausgelöst und nicht nach dem Trennen und Anschließen des Ladegeräts
* Behoben: WLAN-Auslöser wurde beim Trennen der Verbindung nicht zuverlässig ausgelöst
* Behoben: Auf Api-Level <=28 wurde eine Berechtigung für ActivityDetection angefordert, die nicht erteilt werden konnte
* Behoben: Die Aktion "Andere Anwendung starten" startete einen Dienst nicht immer korrekt
* Geändert: targetSdk mußte in Google Play Version auf 33 erhöht werden. Falls das Fehler verursacht, denken Sie darüber nach zur F-Droid oder APK version zu wechseln.

View File

@@ -0,0 +1 @@
* Fixed: Crashes at service start that only affected the Google Play version because of a higher targetSdk

View File

@@ -0,0 +1,2 @@
* Change: Icon changed in Play store version
* Change: Was forced to raise targetSdk to 32 for Google Play version. If that should break something, consider switching to the F-Droid or APK version.

View File

@@ -0,0 +1,6 @@
* Fixed: Added overlay permission for start-phone-call action
* Fixed: Trigger "battery is charging" would only fire once and not after disconnecting and connecting charger
* Fixed: Wifi trigger would not reliably fire upon disconnection
* Fixed: On Api level <=28 a permission was requested for ActivityDetection that could not be granted
* Fixed: Start other application action did not always start a service correctly
* Change: Was forced to raise targetSdk to 33 for Google Play version. If that should break something, consider switching to the F-Droid or APK version.

View File

@@ -0,0 +1,5 @@
* Fixed: Overlay permission for start other program action only required if startByActivity() is selected
* Fixed: Broadcast receiver trigger would not trigger anything, but crash
* Fixed: Bug in Android 14 (not in Automation!!!) required a change when dialing MMI codes containing a # character.
* Added: One can now choose between GET and POST when using triggerURL action
* Added: new action -> take screenshot

View File

@@ -0,0 +1,2 @@
* Cambio: Icono cambiado en la versión de Play Store
* Cambio: Se ha forzado a subir targetSdk a 32 para la versión de Google Play. Si eso rompe algo, considere cambiar a la versión F-Droid o APK.

View File

@@ -0,0 +1,6 @@
* Corregido: Se agregó permiso de superposición para la acción de inicio de llamada telefónica
* Corregido: El disparador "la batería se está cargando" solo se disparaba una vez y no después de desconectar y conectar el cargador
* Corregido: el disparador de Wifi no se disparaba de forma fiable tras la desconexión
* Corregido: En el nivel de API <=28 se solicitaba un permiso para ActivityDetection que no se podía conceder
* Corregido: Iniciar otra acción de aplicación no siempre iniciaba un servicio correctamente
* Cambio: Se ha forzado a subir targetSdk a 33 para la versión de Google Play. Si eso rompe algo, considere cambiar a la versión F-Droid o APK.

View File

@@ -0,0 +1,2 @@
* Changement : Icône modifiée dans la version Play Store
* Changement : Été forcé d'augmenter targetSdk à 32 pour la version Google Play. Si cela devait casser quelque chose, envisagez de passer à la version F-Droid ou APK.

View File

@@ -0,0 +1,6 @@
* Corrigé : Ajout d'une autorisation de superposition pour l'action de démarrage d'un appel téléphonique
* Résolu : La gâchette « la batterie est en charge » ne se déclenchait qu'une seule fois et non après avoir débranché et connecté le chargeur
* Résolu : Le déclencheur Wifi ne se déclenchait pas de manière fiable lors de la déconnexion
* Résolu : Au niveau d'API <=28, une autorisation était demandée pour ActivityDetection qui ne pouvait pas être accordée
* Résolu : L'action Démarrer une autre application ne démarrait pas toujours correctement un service
* Changement : Été forcé d'augmenter targetSdk à 33 pour la version Google Play. Si cela devait casser quelque chose, envisagez de passer à la version F-Droid ou APK.

View File

@@ -0,0 +1,2 @@
* Modifica: l'icona è cambiata nella versione del Play Store
* Modifica: è stato forzato aumentare targetSdk a 32 per la versione di Google Play. Se questo dovesse rompere qualcosa, prendi in considerazione l'idea di passare alla versione F-Droid o APK.

View File

@@ -0,0 +1,6 @@
* Risolto: aggiunta l'autorizzazione di sovrapposizione per l'azione di avvio della chiamata telefonica
* Risolto: il trigger "la batteria è in carica" si attivava solo una volta e non dopo aver scollegato e collegato il caricabatterie
* Risolto: il trigger Wi-Fi non si attivava in modo affidabile alla disconnessione
* Risolto: al livello Api <=28 è stata richiesta un'autorizzazione per ActivityDetection che non poteva essere concessa
* Risolto: l'avvio di un'altra azione dell'applicazione non sempre avviava correttamente un servizio
* Modifica: è stato forzato aumentare targetSdk a 33 per la versione di Google Play. Se questo dovesse rompere qualcosa, prendi in considerazione l'idea di passare alla versione F-Droid o APK.

View File

@@ -0,0 +1,2 @@
* Wijziging: pictogram gewijzigd in Play Store-versie
* Wijziging: Werd gedwongen om targetSdk te verhogen naar 32 voor de Google Play-versie. Als dat iets kapot zou maken, overweeg dan om over te schakelen naar de F-Droid- of APK-versie.

View File

@@ -0,0 +1,6 @@
* Opgelost: overlay-toestemming toegevoegd voor start-telefoongesprek-actie
* Opgelost: trigger "batterij wordt opgeladen" ging maar één keer af en niet na het loskoppelen en aansluiten van de oplader
* Opgelost: wifi-trigger ging niet betrouwbaar af bij het verbreken van de verbinding
* Opgelost: op API-niveau <=28 werd een toestemming gevraagd voor ActivityDetection die niet kon worden verleend
* Opgelost: andere applicatieactie starten startte een service niet altijd correct
* Wijziging: Werd gedwongen om targetSdk te verhogen naar 33 voor de Google Play-versie. Als dat iets kapot zou maken, overweeg dan om over te schakelen naar de F-Droid- of APK-versie.

View File

@@ -0,0 +1,2 @@
* Zmiana: Ikona zmieniona w wersji sklepu Play
* Zmiana: Został zmuszony do podniesienia targetSdk do 32 dla wersji Google Play. Jeśli to powinno coś zepsuć, rozważ przejście na wersję F-Droid lub APK.

View File

@@ -0,0 +1,6 @@
* Naprawiono: Dodano uprawnienie nakładki do akcji start-phone-call
* Naprawiono: Wyzwalacz "bateria się ładuje" uruchamiał się tylko raz, a nie po odłączeniu i podłączeniu ładowarki
* Naprawiono: Wyzwalacz Wi-Fi nie uruchamiał się niezawodnie po rozłączeniu
* Naprawiono: Na poziomie interfejsu API <=28 zażądano uprawnienia do wykrywania aktywności, którego nie można było udzielić
* Naprawiono: Akcja Uruchom inną aplikację nie zawsze poprawnie uruchamiała usługę
* Zmiana: Został zmuszony do podniesienia targetSdk do 33 dla wersji Google Play. Jeśli to powinno coś zepsuć, rozważ przejście na wersję F-Droid lub APK.

View File

@@ -0,0 +1,2 @@
* Изменение: Иконка изменена в версии Play Store
* Изменение: Было вынуждено поднять targetSdk до 32 для версии для Google Play. Если это что-то сломает, подумайте о переходе на версию F-Droid или APK.

View File

@@ -0,0 +1,6 @@
* Исправлено: Добавлено разрешение оверлея для запуска телефонного звонка
* Исправлено: Триггер "батарея заряжается" срабатывал только один раз, а не после отключения и подключения зарядного устройства.
* Исправлено: триггер Wi-Fi не срабатывал при отключении.
* Исправлено: На уровне Api <=28 запрашивалось разрешение для ActivityDetection, которое не могло быть предоставлено.
* Исправлено: Действие «Запуск другого приложения» не всегда корректно запускало службу
* Изменение: Было вынуждено поднять targetSdk до 33 для версии для Google Play. Если это что-то сломает, подумайте о переходе на версию F-Droid или APK.

View File

@@ -0,0 +1,2 @@
* 更改Play商店版本中的图标已更改
* 更改Google Play 版本被迫将 targetSdk 提高到 32。如果这会破坏某些东西请考虑切换到 F-Droid 或 APK 版本。

View File

@@ -0,0 +1,6 @@
* 修复:新增启动电话呼叫操作的覆盖权限
* 修复:"电池正在充电"触发器仅触发一次,断开和连接充电器后不会触发
* 修复Wifi触发器在断开连接时无法可靠地触发
* 已修复:在 API 级别
* 修复:启动其他应用程序操作并不总是正确启动服务
* 更改Google Play 版本被迫将 targetSdk 提高到 33。如果这会破坏某些东西请考虑切换到 F-Droid 或 APK 版本。