diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml
index 7fe8c4c7..f5404b05 100644
--- a/app/src/apkFlavor/AndroidManifest.xml
+++ b/app/src/apkFlavor/AndroidManifest.xml
@@ -202,17 +202,19 @@
-
+
-
+
+
+
+
-
-
+
diff --git a/app/src/fdroidFlavor/AndroidManifest.xml b/app/src/fdroidFlavor/AndroidManifest.xml
index 9c567b89..9cb7f341 100644
--- a/app/src/fdroidFlavor/AndroidManifest.xml
+++ b/app/src/fdroidFlavor/AndroidManifest.xml
@@ -180,8 +180,18 @@
-
+
+
+
+
+
+
+
+
diff --git a/app/src/googlePlayFlavor/AndroidManifest.xml b/app/src/googlePlayFlavor/AndroidManifest.xml
index 71dc8f79..5d9f79ad 100644
--- a/app/src/googlePlayFlavor/AndroidManifest.xml
+++ b/app/src/googlePlayFlavor/AndroidManifest.xml
@@ -175,6 +175,18 @@
+
+
+
+
+
+
+
+
+
+ {
+ @Override
+ public int compareTo(CustomPackageInfo another)
+ {
+ String name1 = "";
+ String name2 = "";
+
+ ApplicationInfo aInfo1 = this.applicationInfo;
+ if (aInfo1 != null)
+ {
+ name1 = (String) ActivityManageNotificationTrigger.this.getPackageManager().getApplicationLabel(aInfo1);
+ }
+ ApplicationInfo aInfo2 = another.applicationInfo;
+ if (aInfo2 != null)
+ {
+ name2 = (String) ActivityManageNotificationTrigger.this.getPackageManager().getApplicationLabel(aInfo2);
+ }
+
+ return name1.compareTo(name2);
+ }
+
+ }
+
+ private static List pInfos = null;
+ public static Action resultingAction;
+
+ private static final String[] supportedIntentTypes = { "boolean", "byte", "char", "double", "float", "int", "long", "short", "String" };
+ private ArrayList intentPairList = new ArrayList();
+
+ ArrayAdapter intentTypeSpinnerAdapter, intentPairAdapter;
+
+ public static void getActivityList(final Context context)
+ {
+ if(pInfos == null)
+ {
+ pInfos = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
+ Collections.sort(pInfos, new Comparator()
+ {
+ public int compare(PackageInfo obj1, PackageInfo obj2)
+ {
+ String name1 = "";
+ String name2 = "";
+
+ ApplicationInfo aInfo1 = obj1.applicationInfo;
+ if (aInfo1 != null)
+ {
+ name1 = (String) context.getPackageManager().getApplicationLabel(aInfo1);
+ }
+ ApplicationInfo aInfo2 = obj2.applicationInfo;
+ if (aInfo2 != null)
+ {
+ name2 = (String) context.getPackageManager().getApplicationLabel(aInfo2);
+ }
+
+ return name1.compareTo(name2);
+ }
+ });
+ }
+ }
+
+ public static String[] getApplicationNameListString(Context myContext)
+ {
+ // Generate the actual list
+ getActivityList(myContext);
+
+ ArrayList returnList = new ArrayList();
+
+ for (PackageInfo pInfo : pInfos)
+ {
+ ApplicationInfo aInfo = pInfo.applicationInfo;
+ if (aInfo != null)
+ {
+ String aLabel;
+
+ aLabel = (String) myContext.getPackageManager().getApplicationLabel(aInfo);
+
+ ActivityInfo[] aInfos = pInfo.activities;
+ if (aInfos != null && aInfos.length > 0) // Only put Applications into the list that have packages.
+ {
+ if(!returnList.contains(aLabel))
+ returnList.add(aLabel);
+ }
+ }
+ }
+
+ return returnList.toArray(new String[returnList.size()]);
+ }
+
+ public static String[] getPackageListString(Context myContext, String applicationLabel)
+ {
+ // Generate the actual list
+ getActivityList(myContext);
+
+ ArrayList returnList = new ArrayList();
+
+ for (PackageInfo pInfo : pInfos)
+ {
+ if(myContext.getPackageManager().getApplicationLabel(pInfo.applicationInfo).equals(applicationLabel))
+ {
+ ActivityInfo[] aInfos = pInfo.activities;
+ if (aInfos != null && aInfos.length > 0)
+ {
+ returnList.add(pInfo.packageName);
+ }
+ }
+ }
+
+ return returnList.toArray(new String[returnList.size()]);
+ }
+
+ public static String[] getPackageListString(Context myContext)
+ {
+ // Generate the actual list
+ getActivityList(myContext);
+
+ ArrayList returnList = new ArrayList();
+
+ for (PackageInfo pInfo : pInfos)
+ {
+ ActivityInfo[] aInfos = pInfo.activities;
+ if (aInfos != null && aInfos.length > 0)
+ {
+ returnList.add(pInfo.packageName);
+ }
+ else
+ Miscellaneous.logEvent("w", "Empty Application", "Application " + myContext.getPackageManager().getApplicationLabel(pInfo.applicationInfo) + " doesn\'t have packages.", 5);
+ }
+
+ return returnList.toArray(new String[returnList.size()]);
+ }
+
+ public static String[] getActivityListForPackageName(String packageName)
+ {
+ ArrayList returnList = new ArrayList();
+
+ for (PackageInfo pInfo : pInfos)
+ {
+ if(pInfo.packageName.equals(packageName))
+ {
+ ActivityInfo[] aInfos = pInfo.activities;
+ if (aInfos != null)
+ {
+ for (ActivityInfo activityInfo : aInfos)
+ {
+ returnList.add(activityInfo.name);
+ }
+ }
+ }
+ }
+
+ return returnList.toArray(new String[returnList.size()]);
+ }
+
+ public static ActivityInfo getActivityInfoForPackageNameAndActivityName(String packageName, String activityName)
+ {
+ for (PackageInfo pInfo : pInfos)
+ {
+ if(pInfo.packageName.equals(packageName))
+ {
+ ActivityInfo[] aInfos = pInfo.activities;
+ if (aInfos != null)
+ {
+ for (ActivityInfo activityInfo : aInfos)
+ {
+ if(activityInfo.name.equals(activityName))
+ return activityInfo;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private AlertDialog getActionStartActivityDialog1()
+ {
+ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
+ alertDialogBuilder.setTitle(getResources().getString(R.string.selectApplication));
+ final String[] applicationArray = ActivityManageNotificationTrigger.getApplicationNameListString(this);
+ alertDialogBuilder.setItems(applicationArray, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ dialog.dismiss();
+ getActionStartActivityDialog2(applicationArray[which]).show();
+ }
+ });
+ AlertDialog alertDialog = alertDialogBuilder.create();
+
+ return alertDialog;
+ }
+ private AlertDialog getActionStartActivityDialog2(String applicationName)
+ {
+ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
+ alertDialogBuilder.setTitle(getResources().getString(R.string.selectPackageOfApplication));
+ final String[] packageArray = ActivityManageNotificationTrigger.getPackageListString(this, applicationName);
+ alertDialogBuilder.setItems(packageArray, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ getActionStartActivityDialog3(packageArray[which]).show();
+ Miscellaneous.messageBox(getResources().getString(R.string.hint), getResources().getString(R.string.chooseActivityHint), ActivityManageNotificationTrigger.this).show();
+
+ }
+ });
+ AlertDialog alertDialog = alertDialogBuilder.create();
+
+ return alertDialog;
+ }
+ private AlertDialog getActionStartActivityDialog3(final String packageName)
+ {
+ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
+ alertDialogBuilder.setTitle(getResources().getString(R.string.selectActivityToBeStarted));
+ final String activityArray[] = ActivityManageNotificationTrigger.getActivityListForPackageName(packageName);
+ alertDialogBuilder.setItems(activityArray, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ ActivityInfo ai = ActivityManageNotificationTrigger.getActivityInfoForPackageNameAndActivityName(packageName, activityArray[which]);
+ tvSelectedActivity.setText(ai.packageName + ";" + ai.name);
+ }
+ });
+ AlertDialog alertDialog = alertDialogBuilder.create();
+
+ return alertDialog;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.action_start_activity);
+
+ lvIntentPairs = (ListView)findViewById(R.id.lvIntentPairs);
+ etParameterName = (EditText)findViewById(R.id.etParameterName);
+ etParameterValue = (EditText)findViewById(R.id.etParameterValue);
+ bSelectApp = (Button)findViewById(R.id.bSelectApp);
+ bAddIntentPair = (Button)findViewById(R.id.bAddIntentPair);
+ bSaveActionStartOtherActivity = (Button)findViewById(R.id.bSaveActionStartOtherActivity);
+ spinnerParameterType = (Spinner)findViewById(R.id.spinnerParameterType);
+ tvSelectedActivity = (TextView)findViewById(R.id.tvSelectedActivity);
+
+ intentTypeSpinnerAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageNotificationTrigger.supportedIntentTypes);
+ spinnerParameterType.setAdapter(intentTypeSpinnerAdapter);
+ intentTypeSpinnerAdapter.notifyDataSetChanged();
+
+ intentPairAdapter = new ArrayAdapter(this, R.layout.text_view_for_poi_listview_smalltextsize, intentPairList);
+
+ bSelectApp.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ GetActivityListTask getActivityListTask = new GetActivityListTask();
+ getActivityListTask.execute();
+ progressDialog = ProgressDialog.show(ActivityManageNotificationTrigger.this, "", ActivityManageNotificationTrigger.this.getResources().getString(R.string.gettingListOfInstalledApplications));
+ }
+ });
+
+ bAddIntentPair.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ // type;name;value
+ if(spinnerParameterType.getSelectedItem().toString().length() == 0)
+ {
+ Toast.makeText(ActivityManageNotificationTrigger.this, getResources().getString(R.string.selectTypeOfIntentPair), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ if(etParameterName.getText().toString().length() == 0)
+ {
+ Toast.makeText(ActivityManageNotificationTrigger.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ if(etParameterValue.getText().toString().length() == 0)
+ {
+ Toast.makeText(ActivityManageNotificationTrigger.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + "/" + etParameterName.getText().toString() + "/" + etParameterValue.getText().toString();
+ intentPairList.add(param);
+
+ spinnerParameterType.setSelection(0);
+ etParameterName.setText("");
+ etParameterValue.setText("");
+
+ updateIntentPairList();
+ }
+ });
+
+ lvIntentPairs.setOnItemLongClickListener(new OnItemLongClickListener()
+ {
+ @Override
+ public boolean onItemLongClick(AdapterView> arg0, View arg1, int arg2, long arg3)
+ {
+ getIntentPairDialog(arg2).show();
+ return false;
+ }
+ });
+
+ bSaveActionStartOtherActivity.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ if(saveAction())
+ {
+ ActivityManageNotificationTrigger.this.setResult(RESULT_OK);
+ finish();
+ }
+ }
+ });
+
+ lvIntentPairs.setOnTouchListener(new OnTouchListener()
+ {
+ @Override
+ public boolean onTouch(View v, MotionEvent event)
+ {
+ v.getParent().requestDisallowInterceptTouchEvent(true);
+ return false;
+ }
+ });
+
+ spinnerParameterType.setOnItemSelectedListener(new OnItemSelectedListener()
+ {
+ @Override
+ public void onItemSelected(AdapterView> arg0, View arg1, int arg2, long arg3)
+ {
+ if(supportedIntentTypes[arg2].equals("double") | supportedIntentTypes[arg2].equals("float") | supportedIntentTypes[arg2].equals("int") | supportedIntentTypes[arg2].equals("long") | supportedIntentTypes[arg2].equals("short"))
+ ActivityManageNotificationTrigger.this.etParameterValue.setInputType(InputType.TYPE_CLASS_NUMBER);
+ else
+ ActivityManageNotificationTrigger.this.etParameterValue.setInputType(InputType.TYPE_CLASS_TEXT);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> arg0)
+ {
+ // TODO Auto-generated method stub
+
+ }
+ });
+
+ Intent i = getIntent();
+ if(i.getBooleanExtra("edit", false) == true)
+ {
+ edit = true;
+ loadValuesIntoGui();
+ }
+ }
+
+ private void loadValuesIntoGui()
+ {
+ String[] params = resultingAction.getParameter2().split(";");
+ if(params.length >= 2)
+ {
+ tvSelectedActivity.setText(params[0] + ";" + params[1]);
+
+ if(params.length > 2)
+ {
+ intentPairList.clear();
+
+ for(int i=2; i
+ {
+ @Override
+ protected Void doInBackground(Void... params)
+ {
+ getActivityList(ActivityManageNotificationTrigger.this);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result)
+ {
+ progressDialog.dismiss();
+ getActionStartActivityDialog1().show();
+ }
+
+
+ }
+}
diff --git a/app/src/main/java/com/jens/automation2/ActivityManageRule.java b/app/src/main/java/com/jens/automation2/ActivityManageRule.java
index 2a208094..1bcd161d 100644
--- a/app/src/main/java/com/jens/automation2/ActivityManageRule.java
+++ b/app/src/main/java/com/jens/automation2/ActivityManageRule.java
@@ -95,6 +95,8 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionScreenBrightnessAdd = 401;
final static int requestCodeActionScreenBrightnessEdit = 402;
final static int requestCodeActionSendTextMessage = 7001;
+ final static int requestCodeTriggerNotificationAdd = 8000;
+ final static int requestCodeTriggerNfcNotificationEdit = 8001;
public static ActivityManageRule getInstance()
{
@@ -466,6 +468,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.bluetooth));
else if(types[i].toString().equals(Trigger_Enum.headsetPlugged.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.headphone));
+ else if(types[i].toString().equals(Trigger_Enum.notification.toString()))
+ items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@@ -536,6 +540,13 @@ public class ActivityManageRule extends Activity
booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
else if(triggerType == Trigger_Enum.process_started_stopped)
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
+ else if(triggerType == Trigger_Enum.notification)
+ {
+ newTrigger.setTriggerType(Trigger_Enum.notification);
+ Intent nfcEditor = new Intent(myContext, ActivityManageNotificationTrigger.class);
+ startActivityForResult(nfcEditor, requestCodeTriggerNotificationAdd);
+ return;
+ }
else if(triggerType == Trigger_Enum.airplaneMode)
booleanChoices = new String[]{getResources().getString(R.string.activated), getResources().getString(R.string.deactivated)};
else if(triggerType == Trigger_Enum.roaming)
@@ -1139,6 +1150,18 @@ public class ActivityManageRule extends Activity
else
Miscellaneous.logEvent("w", "ActivityManageNfc", "No nfc id returned. Assuming abort.", 5);
}
+ else if(requestCode == requestCodeTriggerNotificationAdd)
+ {
+ //add notification
+ if(resultCode == RESULT_OK)
+ {
+ //newTrigger.setNfcTagId(ActivityManageNfc.generatedId);
+ ruleToEdit.getTriggerSet().add(newTrigger);
+ this.refreshTriggerList();
+ }
+ else
+ Miscellaneous.logEvent("w", "ActivityManageNfc", "No nfc id returned. Assuming abort.", 5);
+ }
else if(requestCode == requestCodeActionSpeakTextAdd)
{
if(resultCode == RESULT_OK)
diff --git a/app/src/main/java/com/jens/automation2/AutomationService.java b/app/src/main/java/com/jens/automation2/AutomationService.java
index 487598d3..072eec03 100644
--- a/app/src/main/java/com/jens/automation2/AutomationService.java
+++ b/app/src/main/java/com/jens/automation2/AutomationService.java
@@ -287,6 +287,8 @@ public class AutomationService extends Service implements OnInitListener
myLocationProvider.applySettingsAndRules();
ReceiverCoordinator.applySettingsAndRules();
+
+ Miscellaneous.createDismissableNotification("test", 4711, null);
}
@Override
diff --git a/app/src/main/java/com/jens/automation2/Miscellaneous.java b/app/src/main/java/com/jens/automation2/Miscellaneous.java
index 6b6441e9..f9581db4 100644
--- a/app/src/main/java/com/jens/automation2/Miscellaneous.java
+++ b/app/src/main/java/com/jens/automation2/Miscellaneous.java
@@ -848,7 +848,7 @@ public class Miscellaneous extends Service
mNotificationManager.notify(0, dismissableNotification);*/
}
- public static void createDismissableNotificationSdk26(String textToDisplay, int notificationId, PendingIntent pendingIntent)
+ static void createDismissableNotificationSdk26(String textToDisplay, int notificationId, PendingIntent pendingIntent)
{
NotificationManager mNotificationManager = (NotificationManager) AutomationService.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java
index a9f92ba5..344a27ad 100644
--- a/app/src/main/java/com/jens/automation2/Trigger.java
+++ b/app/src/main/java/com/jens/automation2/Trigger.java
@@ -21,7 +21,7 @@ public class Trigger
*/
public enum Trigger_Enum {
- pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
+ pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
@@ -59,6 +59,8 @@ public class Trigger
return context.getResources().getString(R.string.bluetoothConnection);
case headsetPlugged:
return context.getResources().getString(R.string.triggerHeadsetPlugged);
+ case notification:
+ return context.getResources().getString(R.string.notification);
default:
return "Unknown";
}
diff --git a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java
index 1725f2a8..ea3af70a 100644
--- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java
+++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java
@@ -1,48 +1,55 @@
package com.jens.automation2.receivers;
import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import androidx.annotation.RequiresApi;
+// See here for reference: http://gmariotti.blogspot.com/2013/11/notificationlistenerservice-and-kitkat.html
+
@SuppressLint("OverrideAbstract")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationListener extends NotificationListenerService
{
- static NotificationListener instance;
+ // the title of the notification,
+ public static final String EXTRA_TITLE = "android.title";
+ // the main text payload
+ public static final String EXTRA_TEXT = "android.text";
- public static boolean startNotificationListenerService()
- {
- if(instance == null)
- instance = new NotificationListener();
+ // a third line of text, as supplied to
+ public static final String EXTRA_SUB_TEXT = "android.subText";
- instance.c
- }
+ // a bitmap to be used instead of the small icon when showing the notification payload
+ public static final String EXTRA_LARGE_ICON = "android.largeIcon";
@Override
public void onCreate()
{
super.onCreate();
- nlservicereciver = new NLServiceReceiver();
- IntentFilter filter = new IntentFilter();
- filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
- registerReceiver(nlservicereciver,filter);
}
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onNotificationPosted(StatusBarNotification sbn)
{
super.onNotificationPosted(sbn);
+ String app = sbn.getPackageName();
+ String title = sbn.getNotification().extras.getString(EXTRA_TITLE);
+ String text = sbn.getNotification().extras.getString(EXTRA_TEXT);
}
- @Override
- public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap)
- {
- super.onNotificationPosted(sbn, rankingMap);
- }
+// @Override
+// public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap)
+// {
+// super.onNotificationPosted(sbn, rankingMap);
+// sbn.getNotification().extras.getString(EXTRA_TITLE);
+// sbn.getNotification().extras.getString(EXTRA_TEXT;
+// }
@Override
public void onListenerConnected()
@@ -56,5 +63,9 @@ public class NotificationListener extends NotificationListenerService
super.onListenerDisconnected();
}
-
-}
+ public static void openNotificationAccessWindow(Context context)
+ {
+ Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
+ context.startActivity(intent);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/notification.png b/app/src/main/res/drawable-hdpi/notification.png
new file mode 100644
index 00000000..62b8d94d
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/notification.png differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ebd97e50..9823399d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -611,4 +611,5 @@
Location cannot be determined anymore. Click here to find out why.
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:
Config and log files are stored in folder %1$s
+ Notification
\ No newline at end of file