calendar trigger

This commit is contained in:
jens 2023-12-23 13:55:02 +01:00
parent a21f90acb5
commit 5f278a6ba0
8 changed files with 460 additions and 1 deletions

View File

@ -71,6 +71,7 @@
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@ -143,6 +144,7 @@
<receiver android:name=".receivers.DateTimeListener" /> <receiver android:name=".receivers.DateTimeListener" />
<receiver android:name=".receivers.ConnectivityReceiver" /> <receiver android:name=".receivers.ConnectivityReceiver" />
<receiver android:name=".receivers.TimeZoneListener" /> <receiver android:name=".receivers.TimeZoneListener" />
<receiver android:name=".receivers.CalendarReceiver" />
<receiver <receiver
android:name=".DeviceAdmin" android:name=".DeviceAdmin"
@ -233,6 +235,7 @@
<activity android:name=".ActivityVolumeTest" /> <activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity> <activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityManageTriggerNotification" /> <activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<service <service
android:name=".receivers.NotificationListener" android:name=".receivers.NotificationListener"

View File

@ -69,6 +69,7 @@
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@ -140,6 +141,7 @@
<receiver android:name=".receivers.DateTimeListener" /> <receiver android:name=".receivers.DateTimeListener" />
<receiver android:name=".receivers.ConnectivityReceiver" /> <receiver android:name=".receivers.ConnectivityReceiver" />
<receiver android:name=".receivers.TimeZoneListener" /> <receiver android:name=".receivers.TimeZoneListener" />
<receiver android:name=".receivers.CalendarReceiver" />
<receiver <receiver
android:name=".DeviceAdmin" android:name=".DeviceAdmin"
@ -230,6 +232,7 @@
<activity android:name=".ActivityVolumeTest" /> <activity android:name=".ActivityVolumeTest" />
<activity android:name=".ActivityPermissions"></activity> <activity android:name=".ActivityPermissions"></activity>
<activity android:name=".ActivityManageTriggerNotification" /> <activity android:name=".ActivityManageTriggerNotification" />
<activity android:name=".ActivityManageTriggerCalendar" />
<service <service
android:name=".receivers.NotificationListener" android:name=".receivers.NotificationListener"

View File

@ -66,6 +66,7 @@
<uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/> <uses-permission android:name="com.wireguard.android.permission.CONTROL_TUNNELS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@ -125,6 +126,7 @@
<receiver android:name=".receivers.DateTimeListener" /> <receiver android:name=".receivers.DateTimeListener" />
<receiver android:name=".receivers.ConnectivityReceiver" /> <receiver android:name=".receivers.ConnectivityReceiver" />
<receiver android:name=".receivers.TimeZoneListener" /> <receiver android:name=".receivers.TimeZoneListener" />
<receiver android:name=".receivers.CalendarReceiver" />
<receiver <receiver
android:name=".DeviceAdmin" android:name=".DeviceAdmin"
@ -167,6 +169,7 @@
<activity android:name=".ActivityManageTriggerCheckVariable" /> <activity android:name=".ActivityManageTriggerCheckVariable" />
<activity android:name=".ActivityManageActionCopyToClipboard" /> <activity android:name=".ActivityManageActionCopyToClipboard" />
<activity android:name=".ActivityManageActionLocationService" /> <activity android:name=".ActivityManageActionLocationService" />
<activity android:name=".ActivityManageTriggerCalendar" />
<activity <activity
android:name=".ActivityMainTabLayout" android:name=".ActivityMainTabLayout"

View File

@ -0,0 +1,35 @@
package com.jens.automation2;
import android.app.Activity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import androidx.annotation.Nullable;
public class ActivityManageTriggerCalendar extends Activity
{
CheckBox chkCalendarEventDirection;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Miscellaneous.setDisplayLanguage(this);
setContentView(R.layout.activity_manage_trigger_calendar);
chkCalendarEventDirection = (CheckBox) findViewById(R.id.chkCalendarEventDirection);
chkCalendarEventDirection.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
{
if(checked)
chkCalendarEventDirection.setText(R.string.eventIsCurrentlyHappening);
else
chkCalendarEventDirection.setText(R.string.eventIsCurrentlyNotHappening);
}
});
}
}

View File

@ -14,6 +14,7 @@ import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.BatteryReceiver; import com.jens.automation2.receivers.BatteryReceiver;
import com.jens.automation2.receivers.BluetoothReceiver; import com.jens.automation2.receivers.BluetoothReceiver;
import com.jens.automation2.receivers.BroadcastListener; import com.jens.automation2.receivers.BroadcastListener;
import com.jens.automation2.receivers.CalendarReceiver;
import com.jens.automation2.receivers.ConnectivityReceiver; import com.jens.automation2.receivers.ConnectivityReceiver;
import com.jens.automation2.receivers.DeviceOrientationListener; import com.jens.automation2.receivers.DeviceOrientationListener;
import com.jens.automation2.receivers.HeadphoneJackListener; import com.jens.automation2.receivers.HeadphoneJackListener;
@ -31,6 +32,7 @@ import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Map; import java.util.Map;
public class Trigger public class Trigger
@ -63,6 +65,7 @@ public class Trigger
tethering, tethering,
subSystemState, subSystemState,
checkVariable, checkVariable,
calendarEvent,
phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context) public String getFullName(Context context)
@ -123,6 +126,8 @@ public class Trigger
return context.getResources().getString(R.string.subSystemState); return context.getResources().getString(R.string.subSystemState);
case checkVariable: case checkVariable:
return context.getResources().getString(R.string.checkVariable); return context.getResources().getString(R.string.checkVariable);
case calendarEvent:
return context.getResources().getString(R.string.calendarEvent);
default: default:
return "Unknown"; return "Unknown";
} }
@ -247,11 +252,14 @@ public class Trigger
case subSystemState: case subSystemState:
if(!checkSubSystemState()) if(!checkSubSystemState())
result = false; result = false;
break;
case checkVariable: case checkVariable:
if(!checkVariable()) if(!checkVariable())
result = false; result = false;
break; break;
case calendarEvent:
if(!checkCalendarEvent())
result = false;
break;
default: default:
break; break;
} }
@ -609,6 +617,65 @@ public class Trigger
return false; return false;
} }
boolean checkCalendarEvent()
{
try
{
String[] conditions = this.getTriggerParameter2().split(Trigger.triggerParameter2Split);
List<CalendarReceiver.CalendarEvent> calendarEvents = CalendarReceiver.readCalendarEvents(AutomationService.getInstance());
/*
0 = titleDirection
1 = title;
2 = descriptionDirection
3 = description
4 = eventLocationDirection
5 = eventLocation
6 = availabilityDirection
7 = availability
*/
for(CalendarReceiver.CalendarEvent event : calendarEvents)
{
boolean isActive = Boolean.parseBoolean(conditions[0]);
if(isActive == event.isCurrentActive())
{
if(Miscellaneous.compare(conditions[0], conditions[1], event.title))
{
// title matches according to demands
if(Miscellaneous.compare(conditions[2], conditions[3], event.description))
{
// description matches according to demands
if(Miscellaneous.compare(conditions[4], conditions[5], event.location))
{
// location matches according to demands
if(Miscellaneous.compare(conditions[6], conditions[7], event.availability))
{
// availability matches according to demands
return true;
}
}
}
}
}
}
return false;
//TODO: If trigger demands no calendar event and there is absolutely no future event, we'll need to check for that.
}
catch(Exception e)
{
Miscellaneous.logEvent("e", "checkVariable()", Log.getStackTraceString(e), 1);
}
return false;
}
boolean checkBluetooth() boolean checkBluetooth()
{ {
Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Checking for bluetooth...", this.getParentRule().getName()), 4); Miscellaneous.logEvent("i", Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), String.format("Checking for bluetooth...", this.getParentRule().getName()), 4);

View File

@ -0,0 +1,128 @@
package com.jens.automation2.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class CalendarReceiver extends BroadcastReceiver implements AutomationListenerInterface
{
static BroadcastReceiver calendarReceiverInstance = null;
static boolean calendarReceiverActive = false;
static IntentFilter calendarIntentFilter = null;
@Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_PROVIDER_CHANGED))
{
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.calendarEvent);
for(int i = 0; i < ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
}
}
}
@Override
public void startListener(AutomationService automationService)
{
if(!calendarReceiverActive)
{
if(calendarReceiverInstance == null)
calendarReceiverInstance = new BatteryReceiver();
if(calendarIntentFilter == null)
{
calendarIntentFilter = new IntentFilter();
calendarIntentFilter.addAction(Intent.ACTION_PROVIDER_CHANGED);
}
AutomationService.getInstance().registerReceiver(calendarReceiverInstance, calendarIntentFilter);
calendarReceiverActive = true;
}
}
@Override
public void stopListener(AutomationService automationService)
{
if(calendarReceiverActive)
{
if(calendarReceiverInstance != null)
{
AutomationService.getInstance().unregisterReceiver(calendarReceiverInstance);
calendarReceiverInstance = null;
}
calendarReceiverActive = false;
}
}
@Override
public boolean isListenerRunning()
{
return calendarReceiverActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[]{Trigger.Trigger_Enum.calendarEvent};
}
public static class CalendarEvent
{
public String id, title, description, location, availability;
public Calendar start, end;
public boolean isCurrentActive()
{
Calendar now = Calendar.getInstance();
return now.getTimeInMillis() >= start.getTimeInMillis() && now.getTimeInMillis() < end.getTimeInMillis();
}
}
public static List<CalendarEvent> readCalendarEvents(Context context)
{
Cursor cursor = context.getContentResolver()
.query(
Uri.parse("content://com.android.calendar/events"),
new String[] { "calendar_id", "title", "description", "dtstart", "dtend", "eventLocation", "AVAILABILITY" },
null, null, null);
cursor.moveToFirst();
// fetching calendars name
String CNames[] = new String[cursor.getCount()];
List<CalendarEvent> eventlist = new ArrayList<>();
for (int i = 0; i < CNames.length; i++)
{
CalendarEvent event = new CalendarEvent();
event.id = cursor.getString(1);
event.title = cursor.getString(2);
event.description = cursor.getString(3);
event.start = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(4)));
event.end = Miscellaneous.calendarFromLong(Long.parseLong(cursor.getString(5)));
event.location = cursor.getString(6);
event.availability = cursor.getString(7)
eventlist.add(event);
cursor.moveToNext();
}
return eventlist;
}
}

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/calendarEventCapital"
android:textSize="25dp"
android:layout_marginBottom="@dimen/default_margin" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/direction"/>
<CheckBox
android:id="@+id/chkCalendarEventDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/eventIsCurrentlyHappening"
android:checked="true"/>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/comparisonCaseInsensitive"
android:layout_marginBottom="@dimen/default_margin"/>
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/regularExpressionsIfEquals"
android:layout_marginBottom="@dimen/default_margin"/>
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/title" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerTitleDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etNotificationTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/location" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerTextDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etNotificationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/calendarDescription" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerMarkedAsDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/spinnerMarkedAsOptions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="10dp"
android:layout_marginVertical="@dimen/default_margin"
android:background="#aa000000" />
<TableRow
android:layout_marginBottom="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/markedAs" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinnerTextDirection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etNotificationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</LinearLayout>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bSaveActionCloseNotification"
android:layout_marginTop="@dimen/default_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -905,4 +905,11 @@
<string name="LOCATION_MODE_BATTERY_SAVING" translatable="false">BATTERY_SAVING</string> <string name="LOCATION_MODE_BATTERY_SAVING" translatable="false">BATTERY_SAVING</string>
<string name="LOCATION_MODE_HIGH_ACCURACY" translatable="false">HIGH_ACCURACY</string> <string name="LOCATION_MODE_HIGH_ACCURACY" translatable="false">HIGH_ACCURACY</string>
<string name="triggerUrlVariableHint">The result of this request will be stored in the variable LAST_TRIGGERURL_RESULT if you wish to check it from another rule. In case of HTTP errors like 404 the value will be \"HTTP_ERROR\".</string> <string name="triggerUrlVariableHint">The result of this request will be stored in the variable LAST_TRIGGERURL_RESULT if you wish to check it from another rule. In case of HTTP errors like 404 the value will be \"HTTP_ERROR\".</string>
<string name="calendarEvent">calendar event</string>
<string name="eventIsCurrentlyHappening">Event is currently active</string>
<string name="calendarEventCapital">Calendar event</string>
<string name="location">Location</string>
<string name="calendarDescription">Description/notes</string>
<string name="markedAs">Marked as</string>
<string name="eventIsCurrentlyNotHappening">Event is currently not happening/has ended</string>
</resources> </resources>