Compare commits

..

9 Commits

Author SHA1 Message Date
d4288dfc40 Google shit again. 2021-03-20 12:18:37 +01:00
01f4bba995 Google shit again. 2021-03-20 12:16:39 +01:00
4a2a1a0550 Google shit again. 2021-03-20 02:44:27 +01:00
a693ced32e Background location notifications in googlePlayFlavor 2021-03-18 23:37:21 +01:00
64d1aec910 Google shit again. 2021-03-18 20:00:19 +01:00
221cfa4339 Trying to fix notifications. 2021-03-17 22:58:58 +01:00
810b6f03aa Google shit again. 2021-03-17 21:42:01 +01:00
4e51cbe36e GooglePlayFlavor location engine disabled notice. 2021-03-16 23:23:42 +01:00
722f9f0e6b News opt-in done. 2021-03-15 23:06:37 +01:00
23 changed files with 556 additions and 342 deletions

View File

@ -11,8 +11,8 @@ android {
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion '29.0.2' buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy' useLibrary 'org.apache.http.legacy'
versionCode 99 versionCode 100
versionName "1.6.23" versionName "1.6.24"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@ -137,6 +137,7 @@
<activity android:name=".ActivityManageRule" /> <activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityEditTriggerUrl" /> <activity android:name=".ActivityEditTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityEditSendTextMessage" /> <activity android:name=".ActivityEditSendTextMessage" />
<activity android:name=".ActivityManageTimeFrame" /> <activity android:name=".ActivityManageTimeFrame" />
<activity android:name=".ActivityManageBrightnessSetting" /> <activity android:name=".ActivityManageBrightnessSetting" />

View File

@ -133,6 +133,7 @@
<activity android:name=".ActivityManageRule" /> <activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityEditTriggerUrl" /> <activity android:name=".ActivityEditTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityEditSendTextMessage" /> <activity android:name=".ActivityEditSendTextMessage" />
<activity android:name=".ActivityManageTimeFrame" /> <activity android:name=".ActivityManageTimeFrame" />
<activity android:name=".ActivityManageBrightnessSetting" /> <activity android:name=".ActivityManageBrightnessSetting" />

View File

@ -36,7 +36,6 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@ -63,15 +62,6 @@
<uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- Commented out because of Google Play policy -->
<!--
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
-->
<application <application
android:allowBackup="true" android:allowBackup="true"
android:allowClearUserData="true" android:allowClearUserData="true"
@ -137,6 +127,7 @@
<activity android:name=".ActivityManageRule" /> <activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityEditTriggerUrl" /> <activity android:name=".ActivityEditTriggerUrl" />
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityEditSendTextMessage" /> <activity android:name=".ActivityEditSendTextMessage" />
<activity android:name=".ActivityManageTimeFrame" /> <activity android:name=".ActivityManageTimeFrame" />
<activity android:name=".ActivityManageBrightnessSetting" /> <activity android:name=".ActivityManageBrightnessSetting" />

View File

@ -3,6 +3,7 @@ package com.jens.automation2.receivers;
import android.app.IntentService; import android.app.IntentService;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
@ -13,6 +14,7 @@ import com.google.android.gms.location.ActivityRecognition;
import com.google.android.gms.location.ActivityRecognitionApi; import com.google.android.gms.location.ActivityRecognitionApi;
import com.google.android.gms.location.ActivityRecognitionResult; import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity; import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.ActivityDisplayLongMessage;
import com.jens.automation2.ActivityPermissions; import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService; import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous; import com.jens.automation2.Miscellaneous;
@ -110,6 +112,14 @@ public class ActivityDetectionReceiver extends IntentService implements Automati
} }
public static void startActivityDetectionReceiver() public static void startActivityDetectionReceiver()
{ {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(!ActivityPermissions.havePermission("android.permission.ACTIVITY_RECOGNITION", Miscellaneous.getAnyContext()))
{
Miscellaneous.logEvent("w", "Activity Detection", "Don't have android.permission.ACTIVITY_RECOGNITION. Aborting receiver start..", 2);
return;
}
}
try try
{ {
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Starting ActivityDetectionReceiver", 3); Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Starting ActivityDetectionReceiver", 3);

View File

@ -1,195 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jens.automation2">
package="com.jens.automation2">
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<!-- android:xlargeScreens="true" -->
<uses-feature
android:name="android.hardware.location"
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />
<uses-feature
android:name="android.hardware.location.network"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />
<uses-feature
android:name="android.hardware.microphone"
android:required="false" />
<uses-feature
android:name="android.hardware.wifi"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.hardware.nfc"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- Commented out because of Google Play policy -->
<!--
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
-->
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="@drawable/gears"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="true" />
<meta-data
android:name="google_analytics_adid_collection_enabled"
android:value="false" />
<meta-data
android:name="google_analytics_ssaid_collection_enabled"
android:value="false" />
<activity
android:name=".ActivityMainScreen"
android:label="@string/app_name"></activity>
<activity
android:name=".ActivityManagePoi"
android:label="@string/title_activity_main"></activity>
<activity
android:name=".ActivitySettings"
android:label="@string/title_activity_main"></activity>
<service
android:name=".AutomationService"
android:exported="false"
android:label="@string/title_activity_main" />
<receiver android:name=".receivers.StartupIntentReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<!--<action android:name="android.intent.action.SCREEN_ON" />-->
<!--<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />-->
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.REBOOT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.PackageReplacedReceiver"
android:enabled="true">
<intent-filter>
<!--<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.ACTION_PACKAGE_REPLACED" />-->
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--<data
android:path="com.jens.automation2"
android:scheme="package" />-->
</intent-filter>
</receiver>
<receiver android:name=".receivers.AlarmListener" />
<receiver android:name=".receivers.ConnectivityReceiver" />
<receiver android:name=".receivers.TimeZoneListener" />
<activity android:name=".ActivityManageRule" />
<activity android:name=".ActivityEditTriggerUrl" />
<activity android:name=".ActivityEditSendTextMessage" />
<activity android:name=".ActivityManageTimeFrame" />
<activity android:name=".ActivityManageBrightnessSetting" />
<activity android:name=".ActivityHelp" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<!-- <action android:name="android.nfc.action.TECH_DISCOVERED"/> -->
<!-- <action android:name="android.nfc.action.TAG_DISCOVERED"/> -->
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<!-- <data android:mimeType="application/com.jens.automation2" /> -->
</intent-filter>
<!--
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.jens.automation2" />
</intent-filter>
-->
<!--
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
-->
</activity>
<activity android:name=".ActivityMainPoi" />
<activity android:name=".ActivityMainRules" />
<activity android:name=".ActivityGeneric" />
<activity android:name=".ActivityManageStartActivity" />
<activity android:name=".ActivityManageNfc" />
<activity android:name=".ActivityEditSpeakText" />
<activity android:name=".ActivityManageBluetoothTrigger" />
<activity android:name=".ActivityMainProfiles" />
<activity android:name=".ActivityManageProfile" />
<activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity>
<!-- https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
</application>
</manifest> </manifest>

View File

@ -0,0 +1,56 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.widget.QuickContactBadge;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat;
public class ActivityDisplayLongMessage extends Activity
{
TextView tvMessageTitle, tvLongMessage, tvMessageLink;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_long_message);
tvMessageTitle = (TextView)findViewById(R.id.tvMessageTitle);
tvLongMessage = (TextView)findViewById(R.id.tvLongMessage);
tvMessageLink = (TextView)findViewById(R.id.tvMessageLink);
String title = getIntent().getStringExtra("messageTitle");
String message = getIntent().getStringExtra("longMessage").replace("\\n", Miscellaneous.lineSeparator);
String link = null;
if(getIntent().hasExtra("messageLink"))
link = getIntent().getStringExtra("messageLink");
tvMessageTitle.setText(HtmlCompat.fromHtml(title, HtmlCompat.FROM_HTML_MODE_LEGACY));
tvLongMessage.setText(message);
if(link != null && link.length() > 0)
{
tvMessageLink.setText(HtmlCompat.fromHtml("<u>" + link + "</u>", HtmlCompat.FROM_HTML_MODE_LEGACY));
String finalLink = link;
tvMessageLink.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Uri uriUrl = Uri.parse(finalLink);
Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(launchBrowser);
}
});
}
}
}

View File

@ -53,23 +53,25 @@ public class ActivityMainPoi extends ActivityGeneric
@Override @Override
public void onClick(View v) public void onClick(View v)
{ {
// if(!ActivityPermissions.havePermission(ActivityPermissions.writeExternalStoragePermissionName, ActivityMainPoi.this)) if(Miscellaneous.googleToBlameForLocation(false))
// {
// Toast.makeText(ActivityMainPoi.this, getResources().getString(R.string.appRequiresPermissiontoAccessExternalStorage), Toast.LENGTH_LONG).show();
// return;
// }
if(!ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationCoarse, ActivityMainPoi.this) || !ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationFine, ActivityMainPoi.this))
{ {
Intent permissionIntent = new Intent(ActivityMainPoi.this, ActivityPermissions.class); ActivityMainScreen.openGoogleBlamingWindow();
return;
permissionIntent.putExtra(ActivityPermissions.intentExtraName, new String[] { ActivityPermissions.permissionNameLocationCoarse, ActivityPermissions.permissionNameLocationFine });
startActivityForResult(permissionIntent, requestCodeForPermission);
} }
else else
{ {
buttonAddPoi(); if (!ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationCoarse, ActivityMainPoi.this) || !ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationFine, ActivityMainPoi.this))
{
Intent permissionIntent = new Intent(ActivityMainPoi.this, ActivityPermissions.class);
permissionIntent.putExtra(ActivityPermissions.intentExtraName, new String[]{ActivityPermissions.permissionNameLocationCoarse, ActivityPermissions.permissionNameLocationFine});
startActivityForResult(permissionIntent, requestCodeForPermission);
}
else
{
buttonAddPoi();
}
} }
} }
}); });

View File

@ -2,13 +2,13 @@ package com.jens.automation2;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -29,7 +29,6 @@ import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum; import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider; import com.jens.automation2.location.LocationProvider;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -41,7 +40,7 @@ public class ActivityMainScreen extends ActivityGeneric
private static ActivityMainScreen activityMainScreenInstance = null; private static ActivityMainScreen activityMainScreenInstance = null;
private ToggleButton toggleService, tbLockSound; private ToggleButton toggleService, tbLockSound;
private Button bShowHelp, bPrivacy, bSettingsErase, bSettingsSetToDefault, bVolumeTest, bAddSoundLockTIme; private Button bShowHelp, bPrivacy, bSettingsErase, bSettingsSetToDefault, bVolumeTest, bAddSoundLockTIme;
private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNote1, tvMainScreenNote2, tvMainScreenNote3, tvlockSoundDuration; private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNotePermissions, tvMainScreenNoteFeaturesFromOtherFlavor, tvMainScreenNoteLocationImpossibleBlameGoogle, tvMainScreenNoteNews, tvlockSoundDuration, tvFileStoreLocation;
private ListView lvRuleHistory; private ListView lvRuleHistory;
private ArrayAdapter<Rule> ruleHistoryListViewAdapter; private ArrayAdapter<Rule> ruleHistoryListViewAdapter;
@ -70,10 +69,12 @@ public class ActivityMainScreen extends ActivityGeneric
tvClosestPoi = (TextView) findViewById(R.id.tvClosestPoi); tvClosestPoi = (TextView) findViewById(R.id.tvClosestPoi);
lvRuleHistory = (ListView) findViewById(R.id.lvRuleHistory); lvRuleHistory = (ListView) findViewById(R.id.lvRuleHistory);
tvLastRule = (TextView) findViewById(R.id.tvTimeFrameHelpText); tvLastRule = (TextView) findViewById(R.id.tvTimeFrameHelpText);
tvMainScreenNote1 = (TextView) findViewById(R.id.tvMainScreenNote1); tvMainScreenNotePermissions = (TextView) findViewById(R.id.tvMainScreenNotePermissions);
tvMainScreenNote2 = (TextView) findViewById(R.id.tvMainScreenNote2); tvMainScreenNoteFeaturesFromOtherFlavor = (TextView) findViewById(R.id.tvMainScreenNoteFeaturesFromOtherFlavor);
tvMainScreenNote3 = (TextView) findViewById(R.id.tvMainScreenNote3); tvMainScreenNoteLocationImpossibleBlameGoogle = (TextView) findViewById(R.id.tvMainScreenNoteLocationImpossibleBlameGoogle);
tvMainScreenNoteNews = (TextView) findViewById(R.id.tvMainScreenNoteNews);
tvlockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration); tvlockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tvFileStoreLocation = (TextView)findViewById(R.id.tvFileStoreLocation);
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound); tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener); toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
toggleService.setChecked(AutomationService.isMyServiceRunning(this)); toggleService.setChecked(AutomationService.isMyServiceRunning(this));
@ -95,7 +96,7 @@ public class ActivityMainScreen extends ActivityGeneric
} }
}); });
tvMainScreenNote1.setOnClickListener(new OnClickListener() tvMainScreenNotePermissions.setOnClickListener(new OnClickListener()
{ {
@Override @Override
public void onClick(View v) public void onClick(View v)
@ -291,24 +292,52 @@ public class ActivityMainScreen extends ActivityGeneric
{ {
if(ActivityPermissions.needMorePermissions(activityMainScreenInstance)) if(ActivityPermissions.needMorePermissions(activityMainScreenInstance))
{ {
activityMainScreenInstance.tvMainScreenNote1.setText(R.string.mainScreenPermissionNote); activityMainScreenInstance.tvMainScreenNotePermissions.setText(R.string.mainScreenPermissionNote);
activityMainScreenInstance.tvMainScreenNote1.setVisibility(View.VISIBLE); activityMainScreenInstance.tvMainScreenNotePermissions.setVisibility(View.VISIBLE);
} }
else else
{ {
activityMainScreenInstance.tvMainScreenNote1.setText(""); activityMainScreenInstance.tvMainScreenNotePermissions.setText("");
activityMainScreenInstance.tvMainScreenNote1.setVisibility(View.GONE); activityMainScreenInstance.tvMainScreenNotePermissions.setVisibility(View.GONE);
} }
if(Miscellaneous.restrictedFeaturesConfigured()) if(Miscellaneous.restrictedFeaturesConfigured())
{ {
activityMainScreenInstance.tvMainScreenNote2.setText(R.string.settingsReferringToRestrictedFeatures); activityMainScreenInstance.tvMainScreenNoteFeaturesFromOtherFlavor.setText(R.string.settingsReferringToRestrictedFeatures);
activityMainScreenInstance.tvMainScreenNote2.setVisibility(View.VISIBLE); activityMainScreenInstance.tvMainScreenNoteFeaturesFromOtherFlavor.setVisibility(View.VISIBLE);
} }
else else
{ {
activityMainScreenInstance.tvMainScreenNote2.setText(""); activityMainScreenInstance.tvMainScreenNoteFeaturesFromOtherFlavor.setText("");
activityMainScreenInstance.tvMainScreenNote2.setVisibility(View.GONE); activityMainScreenInstance.tvMainScreenNoteFeaturesFromOtherFlavor.setVisibility(View.GONE);
}
if(Miscellaneous.googleToBlameForLocation(true))
{
// Intent intent = new Intent(AutomationService.this, ActivityDisplayLongMessage.class);
// intent.putExtra("longMessage", getResources().getString(R.string.locationEngineDisabledLong));
// PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
// Miscellaneous.createDismissableNotificationWithDelay(2200, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
// else
// Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setText(R.string.locationEngineDisabledShort);
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setVisibility(View.VISIBLE);
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
openGoogleBlamingWindow();
}
});
}
else
{
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setText("");
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setVisibility(View.GONE);
activityMainScreenInstance.tvMainScreenNoteLocationImpossibleBlameGoogle.setOnClickListener(null);
} }
if (AutomationService.isMyServiceRunning(activityMainScreenInstance)) if (AutomationService.isMyServiceRunning(activityMainScreenInstance))
@ -418,7 +447,56 @@ public class ActivityMainScreen extends ActivityGeneric
Miscellaneous.logEvent("i", "ActivityMainScreen", "Activity not running. No need to update.", 5); Miscellaneous.logEvent("i", "ActivityMainScreen", "Activity not running. No need to update.", 5);
if(activityMainScreenInstance != null) if(activityMainScreenInstance != null)
activityMainScreenInstance.checkForNews(); {
if(!Settings.hasBeenDone(Settings.constNewsOptInDone))
newsOptIn();
else
activityMainScreenInstance.checkForNews();
Settings.considerDone(Settings.constNewsOptInDone);
Settings.writeSettings(Miscellaneous.getAnyContext());
String folder = Miscellaneous.getWriteableFolder();
if(folder != null && folder.length() > 0)
activityMainScreenInstance.tvFileStoreLocation.setText(String.format(activityMainScreenInstance.getResources().getString(R.string.filesStoredAt), folder));
}
}
public static void openGoogleBlamingWindow()
{
Intent intent = new Intent(Miscellaneous.getAnyContext(), ActivityDisplayLongMessage.class);
String message = Miscellaneous.getAnyContext().getResources().getText(R.string.locationEngineDisabledLong).toString();
intent.putExtra("messageTitle", Miscellaneous.getAnyContext().getResources().getString(R.string.locationDisabled));
intent.putExtra("longMessage", message);
intent.putExtra("messageLink", "https://server47.de/automation/fdroidMigration.html");
ActivityMainScreen.getActivityMainScreenInstance().startActivity(intent);
}
static void newsOptIn()
{
AlertDialog.Builder builder = new AlertDialog.Builder(Miscellaneous.getAnyContext());
builder.setMessage(Miscellaneous.getAnyContext().getResources().getString(R.string.newsOptIn));
builder.setPositiveButton(Miscellaneous.getAnyContext().getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Settings.displayNewsOnMainScreen = true;
Settings.writeSettings(Miscellaneous.getAnyContext());
try
{
activityMainScreenInstance.checkForNews();
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "NewsOptIn", "There was a problem showing the news opt-in: " + Log.getStackTraceString(e), 2);
}
}
});
builder.setNegativeButton(Miscellaneous.getAnyContext().getResources().getString(R.string.no), null);
builder.create().show();
} }
@Override @Override
@ -572,57 +650,31 @@ public class ActivityMainScreen extends ActivityGeneric
synchronized void checkForNews() synchronized void checkForNews()
{ {
News.AsyncTaskDownloadNews dnTask = new News.AsyncTaskDownloadNews(); if(Settings.displayNewsOnMainScreen)
dnTask.execute(ActivityMainScreen.this); {
News.AsyncTaskDownloadNews dnTask = new News.AsyncTaskDownloadNews();
// StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); dnTask.execute(ActivityMainScreen.this);
// StrictMode.setThreadPolicy(policy); }
// Calendar now = Calendar.getInstance();
// if (true || Settings.lastNewsPolltime == -1 || now.getTimeInMillis() >= Settings.lastNewsPolltime + (long)(Settings.pollNewsEveryXDays * 24 * 60 * 60 * 1000))
// {
// ArrayList<News> newsToDisplay;
//
//// if(Settings.lastNewsPolltime == -1)
// newsToDisplay = News.downloadNews(ActivityMainScreen.this);
//// else
//// newsToDisplay = News.downloadNews(ActivityMainScreen.this, Miscellaneous.calendarFromLong(Settings.lastNewsPolltime));
//
// if (newsToDisplay.size() > 0)
// {
// activityMainScreenInstance.tvMainScreenNote3.setText(newsToDisplay.get(0).toString());
// activityMainScreenInstance.tvMainScreenNote3.setVisibility(View.VISIBLE);
// }
// else
// {
// activityMainScreenInstance.tvMainScreenNote3.setText("");
// activityMainScreenInstance.tvMainScreenNote3.setVisibility(View.GONE);
// }
// }
} }
public void processNewsResult(ArrayList<News> newsToDisplay) public void processNewsResult(ArrayList<News> newsToDisplay)
{ {
if(Settings.displayNewsOnMainScreen) try
{ {
try if (newsToDisplay.size() > 0)
{ {
if (newsToDisplay.size() > 0) activityMainScreenInstance.tvMainScreenNoteNews.setText(HtmlCompat.fromHtml(newsToDisplay.get(0).toStringHtml(), 0));
{ activityMainScreenInstance.tvMainScreenNoteNews.setVisibility(View.VISIBLE);
activityMainScreenInstance.tvMainScreenNote3.setText(HtmlCompat.fromHtml(newsToDisplay.get(0).toStringHtml(), 0));
activityMainScreenInstance.tvMainScreenNote3.setVisibility(View.VISIBLE);
}
else
{
activityMainScreenInstance.tvMainScreenNote3.setText("");
activityMainScreenInstance.tvMainScreenNote3.setVisibility(View.GONE);
}
} }
catch(Exception e) else
{ {
Miscellaneous.logEvent("e", "Error displaying news", Log.getStackTraceString(e), 3); activityMainScreenInstance.tvMainScreenNoteNews.setText("");
activityMainScreenInstance.tvMainScreenNoteNews.setVisibility(View.GONE);
} }
} }
catch(Exception e)
{
Miscellaneous.logEvent("e", "Error displaying news", Log.getStackTraceString(e), 3);
}
} }
} }

View File

@ -165,7 +165,7 @@ public class ActivityManageRule extends Activity
hideKeyboard(); hideKeyboard();
getActionTypeDialog().show(); getActionTypeDialog().show();
} }
}); });
cmdSaveRule.setOnClickListener(new OnClickListener() cmdSaveRule.setOnClickListener(new OnClickListener()
{ {
@ -502,12 +502,20 @@ public class ActivityManageRule extends Activity
String[] booleanChoices = null; String[] booleanChoices = null;
if(triggerType == Trigger_Enum.pointOfInterest) if(triggerType == Trigger_Enum.pointOfInterest)
{ {
if(PointOfInterest.getPointOfInterestCollection() != null && PointOfInterest.getPointOfInterestCollection().size() > 0) if(Miscellaneous.googleToBlameForLocation(false))
booleanChoices = new String[]{getResources().getString(R.string.entering), getResources().getString(R.string.leaving)}; {
ActivityMainScreen.openGoogleBlamingWindow();
return;
}
else else
{ {
Toast.makeText(myContext, getResources().getString(R.string.noPoisSpecified), Toast.LENGTH_LONG).show(); if (PointOfInterest.getPointOfInterestCollection() != null && PointOfInterest.getPointOfInterestCollection().size() > 0)
return; booleanChoices = new String[]{getResources().getString(R.string.entering), getResources().getString(R.string.leaving)};
else
{
Toast.makeText(myContext, getResources().getString(R.string.noPoisSpecified), Toast.LENGTH_LONG).show();
return;
}
} }
} }
else if(triggerType == Trigger_Enum.timeFrame) else if(triggerType == Trigger_Enum.timeFrame)

View File

@ -231,8 +231,9 @@ public class ActivityPermissions extends Activity
{ {
for (String s : getRequiredPermissions(false)) for (String s : getRequiredPermissions(false))
{ {
if (!havePermission(s, context)) if(!s.equalsIgnoreCase(permissionNameLocationBackground) && !s.equalsIgnoreCase(permissionNameLocationFine) && !s.equalsIgnoreCase(permissionNameLocationCoarse) && Miscellaneous.googleToBlameForLocation(true))
return true; if (!havePermission(s, context))
return true;
} }
} }
@ -298,7 +299,10 @@ public class ActivityPermissions extends Activity
{ {
for (String singlePermission : getPermissionsForRule(rule)) for (String singlePermission : getPermissionsForRule(rule))
if (!havePermission(singlePermission, workingContext)) if (!havePermission(singlePermission, workingContext))
addToArrayListUnique(singlePermission, requiredPermissions); {
if(!singlePermission.equalsIgnoreCase(permissionNameLocationBackground) && !singlePermission.equalsIgnoreCase(permissionNameLocationFine) && !singlePermission.equalsIgnoreCase(permissionNameLocationCoarse) && Miscellaneous.googleToBlameForLocation(true))
addToArrayListUnique(singlePermission, requiredPermissions);
}
} }
} }
@ -977,7 +981,7 @@ public class ActivityPermissions extends Activity
and simply disable features while keeping the notification alive. The user may dismiss it anyway. and simply disable features while keeping the notification alive. The user may dismiss it anyway.
*/ */
Miscellaneous.logEvent("w", "Denied permissions", getResources().getString(R.string.theFollowingPermissionsHaveBeenDenied) + Miscellaneous.explode(deniedPermissions), 3); Miscellaneous.logEvent("w", "Denied permissions", getResources().getString(R.string.theFollowingPermissionsHaveBeenDenied) + Miscellaneous.explode(", ", deniedPermissions), 3);
// this.finish(); // this.finish();
} }
else else

View File

@ -37,9 +37,10 @@ public class AutomationService extends Service implements OnInitListener
protected TextToSpeech ttsEngine = null; protected TextToSpeech ttsEngine = null;
protected final static int notificationId = 1000; protected final static int notificationId = 1000;
protected final static int notificationIdRestrictions = 1005; protected final static int notificationIdRestrictions = 1005;
protected final static int notificationIdLocationRestriction = 1006;
final static String NOTIFICATION_CHANNEL_ID = "com.jens.automation2"; final static String NOTIFICATION_CHANNEL_ID = "com.jens.automation2";
final static String channelName = "Automation notifications"; final static String channelName = "Service notification";
protected static Notification myNotification; protected static Notification myNotification;
protected static NotificationCompat.Builder notificationBuilder = null; protected static NotificationCompat.Builder notificationBuilder = null;
@ -154,7 +155,8 @@ public class AutomationService extends Service implements OnInitListener
{ {
Miscellaneous.logEvent("w", "AutoStart", "Service is started via boot. Settingsfile not available because storage is not mounted, yet. Waiting for 3 seconds.", 4); Miscellaneous.logEvent("w", "AutoStart", "Service is started via boot. Settingsfile not available because storage is not mounted, yet. Waiting for 3 seconds.", 4);
Thread.sleep(3000); Thread.sleep(3000);
} catch (InterruptedException e) }
catch (InterruptedException e)
{ {
e.printStackTrace(); e.printStackTrace();
} }
@ -169,15 +171,13 @@ public class AutomationService extends Service implements OnInitListener
} }
//if still no POIs... //if still no POIs...
if (//PointOfInterest.getPointOfInterestCollection() == null | PointOfInterest.getPointOfInterestCollection().size() == 0 if (Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0)
// &&
Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0
)
{ {
Miscellaneous.logEvent("w", "AutomationService", context.getResources().getString(R.string.serviceWontStart), 1); Miscellaneous.logEvent("w", "AutomationService", context.getResources().getString(R.string.serviceWontStart), 1);
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
return false; return false;
} else }
else
{ {
return true; return true;
} }
@ -318,6 +318,7 @@ public class AutomationService extends Service implements OnInitListener
checkForTtsEngine(); checkForTtsEngine();
checkForPermissions(); checkForPermissions();
checkForRestrictedFeatures(); checkForRestrictedFeatures();
checkForMissingBackgroundLocationPermission();
Actions.context = this; Actions.context = this;
Actions.autoMationServerRef = this; Actions.autoMationServerRef = this;
@ -365,7 +366,10 @@ public class AutomationService extends Service implements OnInitListener
Intent intent = new Intent(AutomationService.this, ActivityPermissions.class); Intent intent = new Intent(AutomationService.this, ActivityPermissions.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0); PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
Miscellaneous.createDismissableNotification(getResources().getString(R.string.appRunningInLimitedMode), ActivityPermissions.notificationIdPermissions, pi); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(1010, getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), ActivityPermissions.notificationIdPermissions, pi);
} }
// else // else
// Toast.makeText(Miscellaneous.getAnyContext(), "Have all required permissions.", Toast.LENGTH_LONG).show(); // Toast.makeText(Miscellaneous.getAnyContext(), "Have all required permissions.", Toast.LENGTH_LONG).show();
@ -385,11 +389,45 @@ public class AutomationService extends Service implements OnInitListener
Intent intent = new Intent(AutomationService.this, ActivityMainTabLayout.class); Intent intent = new Intent(AutomationService.this, ActivityMainTabLayout.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0); PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
// Miscellaneous.createDismissableNotification(getResources().getString(R.string.settingsReferringToRestrictedFeatures), ActivityPermissions.notificationIdPermissions, pi); // Miscellaneous.createDismissableNotification(getResources().getString(R.string.settingsReferringToRestrictedFeatures), ActivityPermissions.notificationIdPermissions, pi);
Miscellaneous.createDismissableNotification(getResources().getString(R.string.settingsReferringToRestrictedFeatures), notificationIdRestrictions, pi); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(3300, getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdRestrictions, pi);
} }
} }
} }
protected void checkForMissingBackgroundLocationPermission()
{
if(Miscellaneous.googleToBlameForLocation(true))
{
Intent intent = new Intent(AutomationService.this, ActivityMainTabLayout.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(2200, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
}
/*
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
if (BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor"))
{
if (Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest))
{
Intent intent = new Intent(AutomationService.this, ActivityMainTabLayout.class);
PendingIntent pi = PendingIntent.getActivity(AutomationService.this, 0, intent, 0);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
Miscellaneous.createDismissableNotificationWithDelay(2200, getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
else
Miscellaneous.createDismissableNotification(getResources().getString(R.string.featuresDisabled), notificationIdLocationRestriction, pi);
}
}
}*/
}
public static void startAutomationService(Context context, boolean startAtBoot) public static void startAutomationService(Context context, boolean startAtBoot)
{ {
if(!(isMyServiceRunning(context))) if(!(isMyServiceRunning(context)))

View File

@ -14,6 +14,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
@ -766,10 +767,63 @@ public class Miscellaneous extends Service
return allHostsValid; return allHostsValid;
} }
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void createDismissableNotificationWithDelay(long delay, String textToDisplay, int notificationId, PendingIntent pendingIntent)
{
/*
Now what's this about?
From SDK 27 onwards you can only fire 1 notification per second:
https://developer.android.com/about/versions/oreo/android-8.1?hl=bn#notify
There are some situations where the service is just being started - resulting in a notification. But we have
additional need to inform the user about something and want to create another notification. That's why we have
to delay it for a moment, but don't want to hold off the main threat.
*/
class AsyncTaskCreateNotification extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... voids)
{
setDefaultBehaviour(this);
try
{
Thread.sleep(delay);
}
catch(Exception e)
{}
createDismissableNotification(textToDisplay, notificationId, pendingIntent);
return null;
}
}
AsyncTaskCreateNotification astCn = new AsyncTaskCreateNotification();
astCn.execute(null, null);
}
private static void setDefaultBehaviour(AsyncTask asyncTask)
{
// without this line debugger will - for some reason - skip all breakpoints in this class
if(android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
// Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.getUncaughtExceptionHandler(activityMainRef, true));
}
@SuppressLint("NewApi") @SuppressLint("NewApi")
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void createDismissableNotification(String textToDisplay, int notificationId, PendingIntent pendingIntent) public static void createDismissableNotification(String textToDisplay, int notificationId, PendingIntent pendingIntent)
{ {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
createDismissableNotificationSdk26(textToDisplay, notificationId, pendingIntent);
return;
}
NotificationManager mNotificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mNotificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder dismissableNotificationBuilder = createDismissableNotificationBuilder(pendingIntent); NotificationCompat.Builder dismissableNotificationBuilder = createDismissableNotificationBuilder(pendingIntent);
@ -781,50 +835,78 @@ public class Miscellaneous extends Service
mNotificationManager.notify(notificationId, dismissableNotification); mNotificationManager.notify(notificationId, dismissableNotification);
/*NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) /*NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon .setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle("Notification!") // title for notification .setContentTitle("Notification!") // title for notification
.setContentText("Hello word") // message for notification .setContentText("Hello word") // message for notification
.setAutoCancel(true); // clear notification after click .setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pi = PendingIntent.getActivity(this,0,intent,Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi); mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager = NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, dismissableNotification);*/ mNotificationManager.notify(0, dismissableNotification);*/
} }
/*protected static Notification.Builder createDismissableNotificationBuilder() public static void createDismissableNotificationSdk26(String textToDisplay, int notificationId, PendingIntent pendingIntent)
{ {
Notification.Builder builder = new Notification.Builder(AutomationService.getInstance()); NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
builder.setContentTitle("Automation");
builder.setSmallIcon(R.drawable.ic_launcher); NotificationCompat.Builder builder;
builder.setCategory(Notification.CATEGORY_EVENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Functionality warnings", NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE);
chan.enableVibration(false);
// chan.setSound(null, null);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(chan);
builder = new NotificationCompat.Builder(AutomationService.getInstance(), NOTIFICATION_CHANNEL_ID);
}
else
builder = new NotificationCompat.Builder(AutomationService.getInstance());
// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
// builder.setCategory(Notification.CATEGORY_SERVICE);
builder.setWhen(System.currentTimeMillis()); builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(pendingIntent);
//static PendingIntent myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0); builder.setContentTitle(AutomationService.getInstance().getResources().getString(R.string.app_name));
builder.setOnlyAlertOnce(true);
//builder.setContentIntent(myPendingIntent); if(Settings.showIconWhenServiceIsRunning)
builder.setSmallIcon(R.drawable.ic_launcher);
// Notification defaultNotification = new Notification(); builder.setContentText(textToDisplay);
*//* Notification defaultNotification = builder.build(); builder.setStyle(new NotificationCompat.BigTextStyle().bigText(textToDisplay));
defaultNotification.icon = R.drawable.ic_launcher; NotificationManager notificationManager = (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
defaultNotification.when = System.currentTimeMillis(); notificationManager.notify(1, builder.build());
// defaultNotification.defaults |= Notification.DEFAULT_VIBRATE;
// defaultNotification.defaults |= Notification.DEFAULT_LIGHTS;
defaultNotification.flags |= Notification.FLAG_AUTO_CANCEL; // Intent notifyIntent = new Intent(context, notification.class);
// defaultNotification.flags |= Notification.FLAG_SHOW_LIGHTS; // notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
defaultNotification.flags |= Notification.FLAG_ONLY_ALERT_ONCE; //
// pendingIntent.getIntentSender().g
// defaultNotification.ledARGB = Color.YELLOW; //
// defaultNotification.ledOnMS = 1500; // PendingIntent pendingIntent = PendingIntent.getActivities(context, 0,
// defaultNotification.ledOffMS = 1500; // new Intent[]{notifyIntent}, PendingIntent.FLAG_UPDATE_CURRENT);
*//* //
return builder; // Notification notification = new Notification.Builder(Miscellaneous.getAnyContext())
}*/ // .setSmallIcon(android.R.drawable.ic_dialog_info)
// .setContentTitle("Automation")
// .setContentText(textToDisplay)
// .setAutoCancel(true)
// .setContentIntent(pendingIntent)
// .build();
// notification.defaults |= Notification.DEFAULT_SOUND;
// NotificationManager notificationManager =
// (NotificationManager) Miscellaneous.getAnyContext().getSystemService(Context.NOTIFICATION_SERVICE);
// notificationManager.notify(1, notification);
}
protected static NotificationCompat.Builder createDismissableNotificationBuilder(PendingIntent myPendingIntent) protected static NotificationCompat.Builder createDismissableNotificationBuilder(PendingIntent myPendingIntent)
{ {
@ -834,7 +916,7 @@ public class Miscellaneous extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{ {
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_LOW); NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
// chan.setLightColor(Color.BLUE); // chan.setLightColor(Color.BLUE);
// chan.enableVibration(false); // chan.enableVibration(false);
// chan.setSound(null, null); // chan.setSound(null, null);
@ -864,13 +946,21 @@ public class Miscellaneous extends Service
return builder; return builder;
} }
public static String explode(ArrayList<String> arrayList) public static String explode(String glue, ArrayList<String> arrayList)
{ {
StringBuilder builder = new StringBuilder(); if(arrayList != null)
for(String s : arrayList) {
builder.append(s); StringBuilder builder = new StringBuilder();
for (String s : arrayList)
builder.append(s + glue);
return builder.toString(); if (builder.length() > 0)
builder.delete(builder.length() - glue.length(), builder.length());
return builder.toString();
}
else
return "";
} }
public static boolean isGooglePlayInstalled(Context context) public static boolean isGooglePlayInstalled(Context context)
@ -1096,4 +1186,25 @@ public class Miscellaneous extends Service
return returnValue; return returnValue;
} }
public static boolean googleToBlameForLocation(boolean checkExistingRules)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
if (BuildConfig.FLAVOR.equalsIgnoreCase("googlePlayFlavor"))
{
if(checkExistingRules)
{
if (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.pointOfInterest))
{
return true;
}
}
else
return true;
}
}
return false;
}
} }

View File

@ -256,7 +256,18 @@ public class News
@Override @Override
protected void onPostExecute(ArrayList arrayList) protected void onPostExecute(ArrayList arrayList)
{ {
ActivityMainScreen.getActivityMainScreenInstance().processNewsResult(arrayList); try
{
ActivityMainScreen.getActivityMainScreenInstance().processNewsResult(arrayList);
}
catch(NullPointerException e)
{
Miscellaneous.logEvent("e", "NewsDownload", "There was a problem displaying the already downloded news, probably ActivityMainScreen isn't currently shown: " + Log.getStackTraceString(e), 2);
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "NewsDownload", "There was a problem displaying the already downloded news: " + Log.getStackTraceString(e), 2);
}
} }
} }
} }

View File

@ -145,7 +145,10 @@ public class ReceiverCoordinator
// startCellLocationChangedReceiver // startCellLocationChangedReceiver
if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()) && WifiBroadcastReceiver.mayCellLocationReceiverBeActivated() && (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.speed))) if(!ConnectivityReceiver.isAirplaneMode(AutomationService.getInstance()) && WifiBroadcastReceiver.mayCellLocationReceiverBeActivated() && (Rule.isAnyRuleUsing(Trigger.Trigger_Enum.pointOfInterest) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.speed)))
CellLocationChangedReceiver.startCellLocationChangedReceiver(); {
if(!Miscellaneous.googleToBlameForLocation(true))
CellLocationChangedReceiver.startCellLocationChangedReceiver();
}
// startBatteryReceiver // startBatteryReceiver
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel)) if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.charging) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.usb_host_connection) | Rule.isAnyRuleUsing(Trigger.Trigger_Enum.batteryLevel))

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -16,6 +17,8 @@ public class Settings implements SharedPreferences
public static final int newsDisplayForXDays = 3; public static final int newsDisplayForXDays = 3;
public static final String folderName = "Automation"; public static final String folderName = "Automation";
public static final String constNewsOptInDone ="newsOptInDone";
public static long minimumDistanceChangeForGpsUpdate; public static long minimumDistanceChangeForGpsUpdate;
public static long minimumDistanceChangeForNetworkUpdate; public static long minimumDistanceChangeForNetworkUpdate;
public static long satisfactoryAccuracyGps; public static long satisfactoryAccuracyGps;
@ -62,6 +65,8 @@ public class Settings implements SharedPreferences
public static boolean noticeAndroid10WifiShown; public static boolean noticeAndroid10WifiShown;
public static long lastNewsPolltime; public static long lastNewsPolltime;
public static ArrayList<String> whatHasBeenDone;
/* /*
Generic settings valid for all installations and not changable Generic settings valid for all installations and not changable
*/ */
@ -250,6 +255,16 @@ public class Settings implements SharedPreferences
noticeAndroid10WifiShown = prefs.getBoolean("noticeAndroid10WifiShown", false); noticeAndroid10WifiShown = prefs.getBoolean("noticeAndroid10WifiShown", false);
lastNewsPolltime = prefs.getLong("lastNewsPolltime", default_lastNewsPolltime); lastNewsPolltime = prefs.getLong("lastNewsPolltime", default_lastNewsPolltime);
String whbdString = prefs.getString("whatHasBeenDone", "");
if(whbdString != null && whbdString.length() > 0)
{
whatHasBeenDone = new ArrayList<>();
for(String s : whbdString.split(";"))
{
whatHasBeenDone.add(s);
}
}
} }
catch(Exception e) catch(Exception e)
{ {
@ -261,6 +276,26 @@ public class Settings implements SharedPreferences
initializeSettings(context, false); initializeSettings(context, false);
} }
} }
public static void considerDone(String key)
{
if(whatHasBeenDone == null)
whatHasBeenDone = new ArrayList<>();
if(!whatHasBeenDone.contains(key))
whatHasBeenDone.add(key);
}
public static boolean hasBeenDone(String key)
{
if(whatHasBeenDone != null)
{
if(whatHasBeenDone.contains(key))
return true;
}
return false;
}
/**Makes sure a settings has a valid setting. If not it will assign a reasonable default setting to it. /**Makes sure a settings has a valid setting. If not it will assign a reasonable default setting to it.
* If force settings will be initialized even if the user has set something.**/ * If force settings will be initialized even if the user has set something.**/
@ -410,6 +445,9 @@ public class Settings implements SharedPreferences
if(!prefs.contains("lastNewsPolltime") | force) if(!prefs.contains("lastNewsPolltime") | force)
editor.putLong("lastNewsPolltime", default_lastNewsPolltime); editor.putLong("lastNewsPolltime", default_lastNewsPolltime);
if(!prefs.contains("whatHasBeenDone") | force)
editor.putString("whatHasBeenDone", "");
editor.commit(); editor.commit();
@ -480,6 +518,8 @@ public class Settings implements SharedPreferences
editor.putLong("lastNewsPolltime", lastNewsPolltime); editor.putLong("lastNewsPolltime", lastNewsPolltime);
editor.putString("whatHasBeenDone", Miscellaneous.explode(";", whatHasBeenDone));
if(lastActivePoi == null) if(lastActivePoi == null)
editor.putString("lastActivePoi", "null"); editor.putString("lastActivePoi", "null");
else else

View File

@ -114,7 +114,14 @@ public class CellLocationChangedReceiver extends PhoneStateListener
myLocationManager = (LocationManager) AutomationService.getInstance().getSystemService(Context.LOCATION_SERVICE); myLocationManager = (LocationManager) AutomationService.getInstance().getSystemService(Context.LOCATION_SERVICE);
currentLocation = getLocation("coarse"); currentLocation = getLocation("coarse");
AutomationService.getInstance().getLocationProvider().setCurrentLocation(currentLocation, false); try
{
AutomationService.getInstance().getLocationProvider().setCurrentLocation(currentLocation, false);
}
catch(NullPointerException e)
{
Miscellaneous.logEvent("e", "LocationProvider", "Location provider is null: " + Log.getStackTraceString(e), 1);
}
} }
else else
{ {
@ -123,7 +130,6 @@ public class CellLocationChangedReceiver extends PhoneStateListener
} }
} }
public Location getLocation(String accuracy) public Location getLocation(String accuracy)
{ {
Criteria crit = new Criteria(); Criteria crit = new Criteria();

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/default_margin">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tvMessageTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30dp" />
<TextView
android:id="@+id/tvLongMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_marginTop="@dimen/default_margin" />
<TextView
android:id="@+id/tvMessageLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_marginTop="@dimen/default_margin" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -27,7 +27,7 @@
</LinearLayout> </LinearLayout>
<TextView <TextView
android:id="@+id/tvMainScreenNote1" android:id="@+id/tvMainScreenNotePermissions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -40,7 +40,7 @@
android:textAppearance="?android:attr/textAppearanceMedium" /> android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView <TextView
android:id="@+id/tvMainScreenNote2" android:id="@+id/tvMainScreenNoteFeaturesFromOtherFlavor"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -53,7 +53,20 @@
android:textAppearance="?android:attr/textAppearanceMedium" /> android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView <TextView
android:id="@+id/tvMainScreenNote3" android:id="@+id/tvMainScreenNoteLocationImpossibleBlameGoogle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:scrollHorizontally="false"
android:textColor="@color/importantMessage"
android:singleLine="false"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/tvMainScreenNoteNews"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -355,6 +368,14 @@
android:text="@string/defaultSettings" /> android:text="@string/defaultSettings" />
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/tvFileStoreLocation"
android:layout_marginVertical="@dimen/default_margin"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout> </LinearLayout>

View File

@ -526,7 +526,7 @@
<string name="continueText">Fortfahren</string> <string name="continueText">Fortfahren</string>
<string name="rule">Regel</string> <string name="rule">Regel</string>
<string name="storeSettings">Einstellungen lesen und speichern</string> <string name="storeSettings">Einstellungen lesen und speichern</string>
<string name="appRunningInLimitedMode">Die Anwendung läuft in einem eingeschränkten Modus, weil nicht alle benötigen Rechte genehmigt wurden.</string> <string name="featuresDisabled">WARNING: Funktionen wurden deaktiviert, Automation läuft in einem eingeschränkten Modus. Klicken Sie hier für mehr Informationen.</string>
<string name="ruleLegend">Grün = aktiviert, rot = deaktiviert, gelb = nicht genügend Rechte</string> <string name="ruleLegend">Grün = aktiviert, rot = deaktiviert, gelb = nicht genügend Rechte</string>
<string name="systemSettingsNote1">Die Berechtigung Betriebssystemeinstellungen ändern zu können, wird benötigt (auch für einfache Dinge wie Bluetooth oder WLAN einschalten). Nach dem Klick auf "Fortfahren" öffnet sich ein Fenster, in dem Sie das für Automation aktivieren müssen. Drücken Sie dann auf Ihren "Zurück" Knopf.</string> <string name="systemSettingsNote1">Die Berechtigung Betriebssystemeinstellungen ändern zu können, wird benötigt (auch für einfache Dinge wie Bluetooth oder WLAN einschalten). Nach dem Klick auf "Fortfahren" öffnet sich ein Fenster, in dem Sie das für Automation aktivieren müssen. Drücken Sie dann auf Ihren "Zurück" Knopf.</string>
<string name="systemSettingsNote2">Anschließend werden in einem zweiten Dialog weitere Berechtigungen angefragt.</string> <string name="systemSettingsNote2">Anschließend werden in einem zweiten Dialog weitere Berechtigungen angefragt.</string>
@ -595,4 +595,7 @@
<string name="manageLocations">Orte anlegen oder ändern</string> <string name="manageLocations">Orte anlegen oder ändern</string>
<string name="publishedOn">veröffentlicht am</string> <string name="publishedOn">veröffentlicht am</string>
<string name="filesHaveBeenMovedTo">Automation benutzt jetzt ein anderes Verzeichnis, um Ihre Daten zu speichern. Alle Ihre Automation-Dateien wurden hierhin verschoben: \"%s\". Die Berechtigung für den externen Speicher wird nun nicht mehr benötigt; Sie können Sie entfernen. In einer künftigen Version wird sie entfernt werden.</string> <string name="filesHaveBeenMovedTo">Automation benutzt jetzt ein anderes Verzeichnis, um Ihre Daten zu speichern. Alle Ihre Automation-Dateien wurden hierhin verschoben: \"%s\". Die Berechtigung für den externen Speicher wird nun nicht mehr benötigt; Sie können Sie entfernen. In einer künftigen Version wird sie entfernt werden.</string>
<string name="locationEngineDisabledShort">Die Position kann nicht mehr bestimmt werden.</string>
<string name="locationEngineDisabledLong">Leider kann die Position nicht mehr bestimmt werden. Großer Dank dafür geht an Google für seine unendliche Weisheit und Großzügigkeit.\\n\\nBeginnend mit Android 10 wurde eine neue Berechtigung eingeführt, die benötigt wird, um als App die Position auch im Hintergrund bestimmen zu können, was, für eine App wie diese, natürlich notwendig ist.\\n\\nWährend ich das grundsätzlich für eine gute Idee halte, gilt das nicht für die Schikanen, die man Entwicklern damit zumutet.\\n\\nWenn man eine App entwickelt, kann man versuchen sich für diese Berechtigung zu qualifizieren, indem man einen Katalog von Bedingungen erfüllt. Leider wurden neue Versionen meiner Anwendung über einen Zeitraum von drei Monaten immer wieder abgelehnt.\\n\\nDas lief auf die immer gleiche Art ab:\\n\\nIch habe eine neue Version eingereicht, die all diese Anforderungen erfüllt hat.\\n\\nGoogles miserabler Entwickler-Support behauptete ich würde sie nicht einhalten.\\n\\nIch habe Beweise geliefert, daß ich alles einhalte.<br />Ich bekam eine Antwort wie "Ich kann Ihnen nicht weiterhelfen.\\n\\nIrgendwann habe ich aufgegeben.\\n\\nDie Folge davon ist nun, daß die Google Play Version keine Positionsbestimmung mehr im Hintergrund durchführen kann. Meine einzige Alternative wäre es gewesen, daß die ganze Anwendung aus dem Store fliegt.\\n\\nDas tut mir sehr leid, aber ich habe mein Bestes gegeben mit einem Kunden\"dienst\" zu diskutieren, der mehrfach beim Turing-Test durchgefallen ist.\\n\\nDie gute Nachricht: Die Anwendung kann es immer noch!\\n\\nAutomation ist nun Open Source Software und kann ab sofort bei F-Droid heruntergeladen werden. F-Droid ist ein freier Appstore, der Ihre Privatsphäre respektiert - statt nur so zu tun wie Google das macht.\\n\\nSichern Sie Ihre Konfiguratinsdatei, deinstallieren Sie dazu diese Anwendung, installieren sie von F-Droid neu, Konfigurationsdatei zurückspielen und fertig.\\n\\nKlicken Sie hier, um mehr herauszufinden:</string>
<string name="filesStoredAt">Konfigurations- und Logdateien werden hier gespeichert: %1$s</string>
</resources> </resources>

View File

@ -523,7 +523,7 @@
<string name="continueText">continue</string> <string name="continueText">continue</string>
<string name="rule">Rule</string> <string name="rule">Rule</string>
<string name="storeSettings">Read and store settings</string> <string name="storeSettings">Read and store settings</string>
<string name="appRunningInLimitedMode">The app is running in limited mode because of lacking permissions.</string> <string name="featuresDisabled">: Features are disabled, Automation is running in limited mode. Click here for more information.</string>
<string name="ruleLegend">Green = enabled, red = disabled, yellow = not enough permissions</string> <string name="ruleLegend">Green = enabled, red = disabled, yellow = not enough permissions</string>
<string name="systemSettingsNote1">The permission to change some OS settings is required (even simple stuff like turn on bluetooth or wifi). After clicking "continue" a window will popup where you need to enable this for Automation. Then hit your "back" key.</string> <string name="systemSettingsNote1">The permission to change some OS settings is required (even simple stuff like turn on bluetooth or wifi). After clicking "continue" a window will popup where you need to enable this for Automation. Then hit your "back" key.</string>
<string name="systemSettingsNote2">Further permissions will be requested in a second dialog afterwards.</string> <string name="systemSettingsNote2">Further permissions will be requested in a second dialog afterwards.</string>

View File

@ -82,7 +82,7 @@
<string name="anyNumber">qualsiasi numero</string> <string name="anyNumber">qualsiasi numero</string>
<string name="anyWifi">qualsiasi wifi</string> <string name="anyWifi">qualsiasi wifi</string>
<string name="appRequiresPermissiontoAccessExternalStorage">Automation richiede lautorizzazione per archiviare e leggere le impostazioni e le regole.</string> <string name="appRequiresPermissiontoAccessExternalStorage">Automation richiede lautorizzazione per archiviare e leggere le impostazioni e le regole.</string>
<string name="appRunningInLimitedMode">L\'applicazione è in esecuzione in modalità limitata a causa di autorizzazioni mancanti.</string> <string name="featuresDisabled">L\'applicazione è in esecuzione in modalità limitata a causa di autorizzazioni mancanti.</string>
<string name="appStarted">App avviata.</string> <string name="appStarted">App avviata.</string>
<string name="appStopped">App terminata.</string> <string name="appStopped">App terminata.</string>
<string name="app_name">Automation</string> <string name="app_name">Automation</string>

View File

@ -527,7 +527,7 @@
<string name="continueText">continue</string> <string name="continueText">continue</string>
<string name="rule">Rule</string> <string name="rule">Rule</string>
<string name="storeSettings">Read and store settings</string> <string name="storeSettings">Read and store settings</string>
<string name="appRunningInLimitedMode">The app is running in limited mode because of lacking permissions.</string> <string name="featuresDisabled">WARNING: Features are disabled, Automation is running in limited mode. Click here for more information.</string>
<string name="ruleLegend">Green = enabled, red = disabled, yellow = not enough permissions</string> <string name="ruleLegend">Green = enabled, red = disabled, yellow = not enough permissions</string>
<string name="systemSettingsNote1">The permission to change some OS settings is required (even simple stuff like turn on bluetooth or wifi). After clicking "continue" a window will popup where you need to enable this for Automation. Then hit your "back" key.</string> <string name="systemSettingsNote1">The permission to change some OS settings is required (even simple stuff like turn on bluetooth or wifi). After clicking "continue" a window will popup where you need to enable this for Automation. Then hit your "back" key.</string>
<string name="systemSettingsNote2">Further permissions will be requested in a second dialog afterwards.</string> <string name="systemSettingsNote2">Further permissions will be requested in a second dialog afterwards.</string>
@ -606,4 +606,9 @@
<string name="displayNewsOnMainScreen">Display application news on main screen</string> <string name="displayNewsOnMainScreen">Display application news on main screen</string>
<string name="displayNewsOnMainScreenDescription">Announcements about this app only, we\'re probably talking about 1-2 per year, not more.</string> <string name="displayNewsOnMainScreenDescription">Announcements about this app only, we\'re probably talking about 1-2 per year, not more.</string>
<string name="filesHaveBeenMovedTo">Automation now uses another path to store your files. All your Automation-files have been moved here: \"%s\". The external storage permission is not required anymore; you can revoke it. It will be removed in a future version.</string> <string name="filesHaveBeenMovedTo">Automation now uses another path to store your files. All your Automation-files have been moved here: \"%s\". The external storage permission is not required anymore; you can revoke it. It will be removed in a future version.</string>
<string name="newsOptIn">Would you like to receive (only important) news about this app on the main screen? Those are downloaded from the developer\'s website. There will be no intrusive notification, just a text on the main screen when you open the app.</string>
<string name="locationDisabled">Location disabled</string>
<string name="locationEngineDisabledShort">Location cannot be determined anymore. Click here to find out why.</string>
<string name="locationEngineDisabledLong">Unfortunately your location cannot be determined anymore. A debt of gratitude is owed to Google for its infinite wisdom and amiableness.\\n\\nLet me explain this further. Starting with Android 10 a new permission was introduced that is needed to determine your location in the background (which of course is required for an app like this). Whilst I consider that a good idea in general the chicanery it involves for developers are not.\\n\\nWhen developing an app you can try to qualify for this permission by abiding to a catalog of requirements. Unfortunately new versions of my app have been rejected over a period of three months. I fulfilled all these requirements, Google\'s shitty development support claimed I would not. After giving them proof that I did after all - I got a response like \"I cannot help you anymore\". Eventually I gave up. \\n\\nAs a consequence the Google Play version can NOT use your location as a trigger anymore. My only alternative option would have been to have this application removed from the store entirely.\\n\\nI\'m very sorry about that, but I\'ve tried my best arguing with a \"support\" that repeatedly failed to pass the Turing test.\\n\\nThe good news: You can still have it all!\\n\\nAutomation is now open source and can be found in F-Droid. That is an app store that really cares about your privacy - rather than just acting like that. Simply backup your config file, uninstall this app, install it again from F-Droid, restore your config file - done.\\n\\nClick here to find out more:</string>
<string name="filesStoredAt">Config and log files are stored in folder %1$s</string>
</resources> </resources>