diff --git a/app/src/main/java/eu/faircode/email/AlarmManagerCompatEx.java b/app/src/main/java/eu/faircode/email/AlarmManagerCompatEx.java
new file mode 100644
index 0000000000..0673fcf6b5
--- /dev/null
+++ b/app/src/main/java/eu/faircode/email/AlarmManagerCompatEx.java
@@ -0,0 +1,43 @@
+package eu.faircode.email;
+
+/*
+ This file is part of FairEmail.
+
+ FairEmail is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ FairEmail is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FairEmail. If not, see .
+
+ Copyright 2018-2021 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.AlarmManagerCompat;
+import androidx.preference.PreferenceManager;
+
+public class AlarmManagerCompatEx {
+ static void setAndAllowWhileIdle(
+ @NonNull Context context, @NonNull AlarmManager am,
+ int type, long trigger, @NonNull PendingIntent pi) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean exact_alarms = prefs.getBoolean("exact_alarms", false);
+
+ if (exact_alarms)
+ AlarmManagerCompat.setExactAndAllowWhileIdle(am, type, trigger, pi);
+ else
+ AlarmManagerCompat.setAndAllowWhileIdle(am, type, trigger, pi);
+ }
+}
diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java
index 3ab8d27876..43bd42573e 100644
--- a/app/src/main/java/eu/faircode/email/Core.java
+++ b/app/src/main/java/eu/faircode/email/Core.java
@@ -40,7 +40,6 @@ import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.app.AlarmManagerCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.Person;
import androidx.core.app.RemoteInput;
@@ -1750,7 +1749,7 @@ class Core {
context, ServiceSend.PI_EXISTS, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, piExists);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, next, piExists);
return;
}
diff --git a/app/src/main/java/eu/faircode/email/EntityMessage.java b/app/src/main/java/eu/faircode/email/EntityMessage.java
index 82b562ef88..b7018aac25 100644
--- a/app/src/main/java/eu/faircode/email/EntityMessage.java
+++ b/app/src/main/java/eu/faircode/email/EntityMessage.java
@@ -27,7 +27,6 @@ import android.content.SharedPreferences;
import android.text.TextUtils;
import androidx.annotation.NonNull;
-import androidx.core.app.AlarmManagerCompat;
import androidx.preference.PreferenceManager;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
@@ -464,7 +463,7 @@ public class EntityMessage implements Serializable {
am.cancel(pi);
} else {
Log.i("Set snooze id=" + id + " wakeup=" + new Date(wakeup));
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, wakeup, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, wakeup, pi);
}
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
index 3e557fbea6..c36ece2ad2 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
@@ -118,6 +118,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
private SwitchCompat swAuthLogin;
private SwitchCompat swAuthNtlm;
private SwitchCompat swAuthSasl;
+ private SwitchCompat swExactAlarms;
private TextView tvProcessors;
private TextView tvMemoryClass;
private TextView tvMemoryUsage;
@@ -142,7 +143,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
"experiments", "wal", "query_threads", "crash_reports", "cleanup_attachments",
"protocol", "debug", "log_level",
"use_modseq", "perform_expunge",
- "auth_plain", "auth_login", "auth_ntlm", "auth_sasl"
+ "auth_plain", "auth_login", "auth_ntlm", "auth_sasl",
+ "exact_alarms"
};
private final static String[] RESET_QUESTIONS = new String[]{
@@ -222,6 +224,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
swAuthLogin = view.findViewById(R.id.swAuthLogin);
swAuthNtlm = view.findViewById(R.id.swAuthNtlm);
swAuthSasl = view.findViewById(R.id.swAuthSasl);
+ swExactAlarms = view.findViewById(R.id.swExactAlarms);
tvProcessors = view.findViewById(R.id.tvProcessors);
tvMemoryClass = view.findViewById(R.id.tvMemoryClass);
tvMemoryUsage = view.findViewById(R.id.tvMemoryUsage);
@@ -577,6 +580,13 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
}
});
+ swExactAlarms.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("exact_alarms", checked).apply();
+ }
+ });
+
btnGC.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -946,6 +956,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
swAuthLogin.setChecked(prefs.getBoolean("auth_login", true));
swAuthNtlm.setChecked(prefs.getBoolean("auth_ntlm", true));
swAuthSasl.setChecked(prefs.getBoolean("auth_sasl", true));
+ swExactAlarms.setChecked(prefs.getBoolean("exact_alarms", false));
tvProcessors.setText(getString(R.string.title_advanced_processors, Runtime.getRuntime().availableProcessors()));
diff --git a/app/src/main/java/eu/faircode/email/ServiceSend.java b/app/src/main/java/eu/faircode/email/ServiceSend.java
index c90b58b012..0ec854fbb4 100644
--- a/app/src/main/java/eu/faircode/email/ServiceSend.java
+++ b/app/src/main/java/eu/faircode/email/ServiceSend.java
@@ -35,7 +35,6 @@ import android.os.PowerManager;
import android.text.TextUtils;
import androidx.annotation.NonNull;
-import androidx.core.app.AlarmManagerCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Observer;
@@ -840,7 +839,7 @@ public class ServiceSend extends ServiceBase implements SharedPreferences.OnShar
long trigger = System.currentTimeMillis() + delay;
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi);
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, trigger, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, trigger, pi);
}
static void watchdog(Context context) {
diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
index a19a6888b1..09432f95ad 100644
--- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
+++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
@@ -40,7 +40,6 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import androidx.core.app.AlarmManagerCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.MediatorLiveData;
@@ -150,7 +149,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
"download_headers", "download_eml",
"prefer_ip4", "standalone_vpn", "tcp_keep_alive", "ssl_harden", // force reconnect
"experiments", "debug", "protocol", // force reconnect
- "auth_plain", "auth_login", "auth_ntlm", "auth_sasl" // force reconnect
+ "auth_plain", "auth_login", "auth_ntlm", "auth_sasl", // force reconnect
+ "exact_alarms" // force schedule
));
static final int PI_ALARM = 1;
@@ -1900,7 +1900,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
long trigger = System.currentTimeMillis() + duration;
EntityLog.log(this, "### " + account.name + " keep alive" +
" wait=" + account.poll_interval + " until=" + new Date(trigger));
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, trigger, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(ServiceSynchronize.this, am, AlarmManager.RTC_WAKEUP, trigger, pi);
try {
wlAccount.release();
@@ -2108,7 +2108,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
try {
long trigger = System.currentTimeMillis() + backoff * 1000L;
EntityLog.log(this, "### " + account.name + " backoff until=" + new Date(trigger));
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, trigger, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(ServiceSynchronize.this, am, AlarmManager.RTC_WAKEUP, trigger, pi);
try {
db.account().setAccountBackoff(account.id, trigger);
@@ -2451,7 +2451,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
Log.i("Schedule next=" + new Date(next));
Log.i("Schedule poll=" + poll);
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, next, pi);
if (sync & poll) {
at = now + 30 * 1000L;
@@ -2484,10 +2484,10 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
EntityLog.log(context, "Poll next=" + new Date(next));
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, piSync);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, next, piSync);
}
} else
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, at, piSync);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, at, piSync);
}
static long[] getSchedule(Context context) {
@@ -2598,7 +2598,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
if (next < now + WATCHDOG_INTERVAL / 5)
next += WATCHDOG_INTERVAL;
Log.i("Sync watchdog at " + new Date(next));
- AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, pi);
+ AlarmManagerCompatEx.setAndAllowWhileIdle(context, am, AlarmManager.RTC_WAKEUP, next, pi);
} else
am.cancel(pi);
}
diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml
index 017bf8888a..1d86191abc 100644
--- a/app/src/main/res/layout/fragment_options_misc.xml
+++ b/app/src/main/res/layout/fragment_options_misc.xml
@@ -601,6 +601,17 @@
app:layout_constraintTop_toBottomOf="@id/swAuthNtlm"
app:switchPadding="12dp" />
+
+
+ app:layout_constraintTop_toBottomOf="@id/swExactAlarms" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5debb8c0f4..acc82b69bc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -296,6 +296,7 @@
Receive messages for all accounts
When
+ Automatically optimize
Always receive messages for these accounts
Schedule
Advanced
@@ -433,6 +434,9 @@
Synchronize on start
Double \'back\' to exit
+ Suggest actions (Android 10+)
+ Suggest reply texts (Android 10+)
+ Detect message text language
Pull down to refresh
Scroll to top on receiving new messages
Double tap to mark message read/unread
@@ -533,9 +537,6 @@
Allow other apps to search in messages
Show frequently used contacts in Android share menu
- Suggest actions (Android 10+)
- Suggest reply texts (Android 10+)
- Detect message text language
Build search index
%1$d / %2$d messages indexed (%3$s)
Classify messages
@@ -544,27 +545,27 @@
Language
System
Periodically check if FairEmail is still active
+ Check for GitHub updates
+ Check weekly instead of daily
+ Try experimental features
+ Send error reports
+ Delete attachments of old messages
+ Cleanup
+ Last cleanup: %1$s
+ App settings
+ More options
+ Protocol logging
+ Debug logging
+ Debug mode
+ Limit parallel database access
+ WAL (debug only)
MODSEQ (debug only)
EXPUNGE (debug only)
PLAIN (debug only)
LOGIN (debug only)
NTLM (debug only)
SASL (debug only)
- Automatically optimize
- Check for GitHub updates
- Check weekly instead of daily
- Try experimental features
- Limit parallel database access
- WAL (debug only)
- Send error reports
- Protocol logging
- Debug logging
- Debug mode
- Delete attachments of old messages
- Cleanup
- Last cleanup: %1$s
- App settings
- More options
+ Use exact timers (debug only)
Processors: %1$d
Memory class: %1$s/%2$s Total: %3$s
Memory usage: %1$s/%2$s Native: %3$s