Calendar trigger

This commit is contained in:
Jens 2023-12-30 23:26:27 +01:00
parent 97a3344e81
commit 81a205a8db
6 changed files with 123 additions and 16 deletions

View File

@ -75,6 +75,9 @@
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-feature <uses-feature

View File

@ -73,6 +73,9 @@
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-feature <uses-feature
android:name="android.hardware.telephony" android:name="android.hardware.telephony"

View File

@ -70,6 +70,9 @@
<uses-permission <uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS" android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<application <application
android:allowBackup="true" android:allowBackup="true"

View File

@ -54,6 +54,7 @@ public class ActivityPermissions extends Activity
private static final int requestCodeForPermissionNotificationAccessAndroid13 = 12049; private static final int requestCodeForPermissionNotificationAccessAndroid13 = 12049;
private static final int requestCodeForPermissionsManageOverlay = 12050; private static final int requestCodeForPermissionsManageOverlay = 12050;
private static final int requestCodeForPermissionsAccessibility = 12051; private static final int requestCodeForPermissionsAccessibility = 12051;
private static final int requestCodeForPermissionsScheduleExactAlarms = 12052;
protected String[] specificPermissionsToRequest = null; protected String[] specificPermissionsToRequest = null;
public static String intentExtraName = "permissionsToBeRequested"; public static String intentExtraName = "permissionsToBeRequested";
@ -558,6 +559,8 @@ public class ActivityPermissions extends Activity
addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions); addToArrayListUnique(Manifest.permission.INTERNET, requiredPermissions);
break; break;
case timeFrame: case timeFrame:
if(Build.VERSION.SDK_INT >= 31 && Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 31)
addToArrayListUnique(Manifest.permission.SCHEDULE_EXACT_ALARM, requiredPermissions);
break; break;
case usb_host_connection: case usb_host_connection:
addToArrayListUnique(Manifest.permission.READ_PHONE_STATE, requiredPermissions); addToArrayListUnique(Manifest.permission.READ_PHONE_STATE, requiredPermissions);
@ -582,6 +585,8 @@ public class ActivityPermissions extends Activity
break; break;
case calendarEvent: case calendarEvent:
addToArrayListUnique(Manifest.permission.READ_CALENDAR, requiredPermissions); addToArrayListUnique(Manifest.permission.READ_CALENDAR, requiredPermissions);
if(Build.VERSION.SDK_INT >= 31 && Miscellaneous.getTargetSDK(Miscellaneous.getAnyContext()) >= 31)
addToArrayListUnique(Manifest.permission.SCHEDULE_EXACT_ALARM, requiredPermissions);
break; break;
default: default:
break; break;
@ -831,6 +836,12 @@ public class ActivityPermissions extends Activity
case Manifest.permission.WRITE_EXTERNAL_STORAGE: case Manifest.permission.WRITE_EXTERNAL_STORAGE:
usingElements.add(getResources().getString(R.string.storeSettings)); usingElements.add(getResources().getString(R.string.storeSettings));
break; break;
case Manifest.permission.SCHEDULE_EXACT_ALARM:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.timeFrame))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.calendarEvent))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
break;
case Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE: case Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE:
for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.notification)) for(String ruleName : getRulesUsing(Trigger.Trigger_Enum.notification))
usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName)); usingElements.add(String.format(getResources().getString(R.string.ruleXrequiresThis), ruleName));
@ -1098,6 +1109,10 @@ public class ActivityPermissions extends Activity
if (requestCode == requestCodeForPermissionsAccessibility) if (requestCode == requestCodeForPermissionsAccessibility)
if(havePermission(Manifest.permission.BIND_ACCESSIBILITY_SERVICE, ActivityPermissions.this)) if(havePermission(Manifest.permission.BIND_ACCESSIBILITY_SERVICE, ActivityPermissions.this))
requestPermissions(cachedPermissionsToRequest, true); requestPermissions(cachedPermissionsToRequest, true);
if (requestCode == requestCodeForPermissionsScheduleExactAlarms)
if(havePermission(Manifest.permission.SCHEDULE_EXACT_ALARM, ActivityPermissions.this))
requestPermissions(cachedPermissionsToRequest, true);
} }
} }
@ -1225,6 +1240,22 @@ public class ActivityPermissions extends Activity
return; return;
} }
else if (s.equalsIgnoreCase(Manifest.permission.SCHEDULE_EXACT_ALARM))
{
AlertDialog diag = Miscellaneous.messageBox(getResources().getString(R.string.info), getResources().getString(R.string.alarmsPermissionHint), ActivityPermissions.this);
diag.setOnDismissListener(new DialogInterface.OnDismissListener()
{
@Override
public void onDismiss(DialogInterface dialogInterface)
{
requiredPermissions.remove(s);
cachedPermissionsToRequest = requiredPermissions;
requestScheduleExactAlarms();
}
});
diag.show();
return;
}
else if(s.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) else if(s.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
{ {
requiredPermissions.remove(s); requiredPermissions.remove(s);
@ -1310,6 +1341,14 @@ public class ActivityPermissions extends Activity
startActivityForResult(intent, requestCodeForPermissionsNotifications); startActivityForResult(intent, requestCodeForPermissionsNotifications);
} }
void requestScheduleExactAlarms()
{
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
startActivityForResult(intent, requestCodeForPermissionsScheduleExactAlarms);
}
protected void applyChanges() protected void applyChanges()
{ {
AutomationService service = AutomationService.getInstance(); AutomationService service = AutomationService.getInstance();

View File

@ -1,11 +1,15 @@
package com.jens.automation2.receivers; package com.jens.automation2.receivers;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -37,6 +41,8 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
static Timer timer = null; static Timer timer = null;
static TimerTask timerTask = null; static TimerTask timerTask = null;
static Calendar nextWakeup = null; static Calendar nextWakeup = null;
static AlarmManager alarmManager = null;
static boolean alarmHasChanged = false;
public static CalendarReceiver getInstance() public static CalendarReceiver getInstance()
{ {
@ -262,19 +268,46 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
return calendarEventsCache; return calendarEventsCache;
} }
public static class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Miscellaneous.logEvent("i", "AlarmReceiver", "Received alarm for calendar receiver.", 5);
routineAtAlarm();
}
}
protected static void routineAtAlarm()
{
checkForRules(Miscellaneous.getAnyContext());
// Set next timer
calculateNextWakeup();
armOrRearmTimer();
}
private static void armOrRearmTimer() private static void armOrRearmTimer()
{
PendingIntent pi = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (alarmManager == null)
{
alarmManager = (AlarmManager) Miscellaneous.getAnyContext().getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(Miscellaneous.getAnyContext(), AlarmReceiver.class);
pi = PendingIntent.getBroadcast(Miscellaneous.getAnyContext(), 0, i, 0);
}
}
else
{ {
timerTask = new TimerTask() timerTask = new TimerTask()
{ {
@Override @Override
public void run() public void run()
{ {
checkForRules(Miscellaneous.getAnyContext()); routineAtAlarm();
// Set next timer
calculateNextWakeup();
armOrRearmTimer();
} }
}; };
@ -284,6 +317,7 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
timer.purge(); timer.purge();
} }
timer = new Timer(); timer = new Timer();
}
if(nextWakeup == null) if(nextWakeup == null)
{ {
@ -293,8 +327,27 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
// If it's now filled, go on // If it's now filled, go on
if(nextWakeup != null) if(nextWakeup != null)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && alarmManager.canScheduleExactAlarms()))
{
try
{
alarmManager.cancel(pi);
}
catch (Exception e)
{
}
Miscellaneous.logEvent("i", "armOrRearmTimer()", "Setting calendar alarm for " + nextWakeup.toString(), 5);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextWakeup.getTimeInMillis(), pi);
}
}
else
timer.schedule(timerTask, nextWakeup.getTimeInMillis()); timer.schedule(timerTask, nextWakeup.getTimeInMillis());
} }
}
private static void calculateNextWakeup() private static void calculateNextWakeup()
{ {
@ -313,6 +366,8 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{ {
nextWakeup = event.end; nextWakeup = event.end;
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing end of event " + event.title + " as next wakeup.", 5); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing end of event " + event.title + " as next wakeup.", 5);
if(!alarmHasChanged)
alarmHasChanged = true;
} }
} }
else else
@ -321,6 +376,8 @@ public class CalendarReceiver extends BroadcastReceiver implements AutomationLis
{ {
nextWakeup = event.start; nextWakeup = event.start;
Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing start of event " + event.title + " as next wakeup.", 5); Miscellaneous.logEvent("i", "calculateNextWakeupForCalendar()", "Choosing start of event " + event.title + " as next wakeup.", 5);
if(!alarmHasChanged)
alarmHasChanged = true;
} }
} }
} }

View File

@ -931,4 +931,6 @@
<string name="permissionCalendarRequired">The permission to read your calendar will be required for a calendar trigger. It will already be required to populate the calendar fields in this window.</string> <string name="permissionCalendarRequired">The permission to read your calendar will be required for a calendar trigger. It will already be required to populate the calendar fields in this window.</string>
<string name="noCalendarsOnYourDevice">It appears like no calendars have been set up on your device. You can save this trigger, but it will never return true.</string> <string name="noCalendarsOnYourDevice">It appears like no calendars have been set up on your device. You can save this trigger, but it will never return true.</string>
<string name="errorReadingCalendars">There was an error reading the calendars on your device.</string> <string name="errorReadingCalendars">There was an error reading the calendars on your device.</string>
<string name="android.permission.SCHEDULE_EXACT_ALARM">Schedule exact alarms</string>
<string name="alarmsPermissionHint">After clicking OK a window will open. Please select Automation there and allow the app to schedule exact alarms.</string>
</resources> </resources>