mirror of
https://github.com/M66B/FairEmail.git
synced 2026-01-03 11:28:41 +01:00
Improved boot
This commit is contained in:
@@ -58,7 +58,8 @@ public class ActivityMain extends AppCompatActivity implements FragmentManager.O
|
||||
startActivity(new Intent(ActivityMain.this, ActivitySetup.class));
|
||||
else {
|
||||
startActivity(new Intent(ActivityMain.this, ActivityView.class));
|
||||
ServiceSynchronize.init(ActivityMain.this, false);
|
||||
ServiceSynchronize.boot(ActivityMain.this);
|
||||
ServiceSend.boot(ActivityMain.this);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
|
||||
if (checked) {
|
||||
if (Helper.isPro(getContext())) {
|
||||
prefs.edit().putBoolean("schedule", true).apply();
|
||||
ServiceSynchronize.schedule(getContext());
|
||||
ServiceSynchronize.reschedule(getContext());
|
||||
} else {
|
||||
swSchedule.setChecked(false);
|
||||
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
|
||||
@@ -645,7 +645,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
|
||||
editor.putBoolean("schedule", true);
|
||||
editor.apply();
|
||||
|
||||
ServiceSynchronize.schedule(getContext());
|
||||
ServiceSynchronize.reschedule(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,43 +23,14 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||
|
||||
public class ReceiverAutostart extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(final Context context, Intent intent) {
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) ||
|
||||
Intent.ACTION_MY_PACKAGE_REPLACED.equals(intent.getAction())) {
|
||||
EntityLog.log(context, intent.getAction());
|
||||
|
||||
ServiceSynchronize.init(context, true);
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
List<EntityMessage> messages = db.message().getSnoozed();
|
||||
for (EntityMessage message : messages)
|
||||
EntityMessage.snooze(context, message.id, message.ui_snoozed);
|
||||
|
||||
EntityFolder outbox = db.folder().getOutbox();
|
||||
if (outbox == null)
|
||||
return;
|
||||
|
||||
if (db.operation().getOperations(outbox.id).size() > 0)
|
||||
ServiceSend.start(context);
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
Log.i("Received " + intent);
|
||||
ServiceSynchronize.boot(context);
|
||||
ServiceSend.boot(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ import androidx.lifecycle.Observer;
|
||||
public class ServiceSend extends LifecycleService {
|
||||
private int lastUnsent = 0;
|
||||
|
||||
private static boolean booted = false;
|
||||
|
||||
private static final int IDENTITY_ERROR_AFTER = 30; // minutes
|
||||
|
||||
@Override
|
||||
@@ -413,6 +415,27 @@ public class ServiceSend extends LifecycleService {
|
||||
}
|
||||
}
|
||||
|
||||
static void boot(final Context context) {
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DB db = DB.getInstance(context);
|
||||
EntityFolder outbox = db.folder().getOutbox();
|
||||
if (outbox != null && db.operation().getOperations(outbox.id).size() > 0)
|
||||
start(context);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
static void start(Context context) {
|
||||
context.startService(new Intent(context, ServiceSend.class));
|
||||
}
|
||||
|
||||
@@ -89,6 +89,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
private TupleAccountStats lastStats = new TupleAccountStats();
|
||||
private ServiceManager serviceManager = new ServiceManager();
|
||||
|
||||
private static boolean booted = false;
|
||||
|
||||
private static final int CONNECT_BACKOFF_START = 8; // seconds
|
||||
private static final int CONNECT_BACKOFF_MAX = 64; // seconds (totally 2 minutes)
|
||||
private static final int CONNECT_BACKOFF_AlARM = 15; // minutes
|
||||
@@ -97,7 +99,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
private static final int BACKOFF_ERROR_AFTER = 16; // seconds
|
||||
private static final long STOP_DELAY = 5000L; // milliseconds
|
||||
|
||||
static final int PI_SCHEDULE = 1;
|
||||
static final int PI_ALARM = 1;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -165,15 +167,13 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
|
||||
if (action != null)
|
||||
try {
|
||||
final String[] parts = action.split(":");
|
||||
switch (parts[0]) {
|
||||
switch (action) {
|
||||
case "init":
|
||||
// Network events will manage the service
|
||||
serviceManager.service_init(intent.getBooleanExtra("boot", false));
|
||||
serviceManager.service_init();
|
||||
break;
|
||||
|
||||
case "schedule":
|
||||
serviceManager.service_schedule();
|
||||
case "alarm":
|
||||
serviceManager.service_alarm();
|
||||
break;
|
||||
|
||||
case "reload":
|
||||
@@ -941,19 +941,14 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
return (db.account().getSynchronizingAccounts(false).size() > 0);
|
||||
}
|
||||
|
||||
private void service_init(boolean boot) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service init boot=" + boot);
|
||||
|
||||
if (boot)
|
||||
next_schedule();
|
||||
|
||||
if (!isEnabled())
|
||||
stopSelf();
|
||||
private void service_init() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service init");
|
||||
// Network events will manage the service
|
||||
}
|
||||
|
||||
private void service_schedule() {
|
||||
next_schedule();
|
||||
service_reload("schedule");
|
||||
private void service_alarm() {
|
||||
schedule(ServiceSynchronize.this);
|
||||
service_reload("alarm");
|
||||
}
|
||||
|
||||
private void service_reload(String reason) {
|
||||
@@ -1071,61 +1066,6 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
state = null;
|
||||
}
|
||||
|
||||
private void next_schedule() {
|
||||
Intent schedule = new Intent(ServiceSynchronize.this, ServiceSynchronize.class);
|
||||
schedule.setAction("schedule");
|
||||
PendingIntent piSchedule = PendingIntent.getService(
|
||||
ServiceSynchronize.this, PI_SCHEDULE, schedule, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
am.cancel(piSchedule);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
if (!prefs.getBoolean("schedule", false))
|
||||
return;
|
||||
|
||||
int minuteStart = prefs.getInt("schedule_start", 0);
|
||||
int minuteEnd = prefs.getInt("schedule_end", 0);
|
||||
|
||||
if (minuteEnd <= minuteStart)
|
||||
minuteEnd += 24 * 60;
|
||||
|
||||
Calendar calStart = Calendar.getInstance();
|
||||
calStart.set(Calendar.HOUR_OF_DAY, minuteStart / 60);
|
||||
calStart.set(Calendar.MINUTE, minuteStart % 60);
|
||||
calStart.set(Calendar.SECOND, 0);
|
||||
calStart.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Calendar calEnd = Calendar.getInstance();
|
||||
calEnd.set(Calendar.HOUR_OF_DAY, minuteEnd / 60);
|
||||
calEnd.set(Calendar.MINUTE, minuteEnd % 60);
|
||||
calEnd.set(Calendar.SECOND, 0);
|
||||
calEnd.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
long now = new Date().getTime();
|
||||
if (now > calEnd.getTimeInMillis()) {
|
||||
calStart.set(Calendar.DAY_OF_MONTH, calStart.get(Calendar.DAY_OF_MONTH) + 1);
|
||||
calEnd.set(Calendar.DAY_OF_MONTH, calEnd.get(Calendar.DAY_OF_MONTH) + 1);
|
||||
}
|
||||
|
||||
long start = calStart.getTimeInMillis();
|
||||
long end = calEnd.getTimeInMillis();
|
||||
long next = (now < start ? start : end);
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Schedule now=" + new Date(now));
|
||||
EntityLog.log(ServiceSynchronize.this, "Schedule start=" + new Date(start));
|
||||
EntityLog.log(ServiceSynchronize.this, "Schedule end=" + new Date(end));
|
||||
EntityLog.log(ServiceSynchronize.this, "Schedule next=" + new Date(next));
|
||||
|
||||
boolean enabled = (now >= start && now < end);
|
||||
prefs.edit().putBoolean("enabled", enabled).apply();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, next, piSchedule);
|
||||
else
|
||||
am.set(AlarmManager.RTC_WAKEUP, next, piSchedule);
|
||||
}
|
||||
|
||||
private void queue_reload(final boolean start, final String reason) {
|
||||
final boolean doStop = started;
|
||||
final boolean doStart = (start && isEnabled() && suitableNetwork());
|
||||
@@ -1192,20 +1132,103 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
}
|
||||
}
|
||||
|
||||
public static void init(Context context, boolean boot) {
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("init")
|
||||
.putExtra("boot", boot));
|
||||
private static void schedule(Context context) {
|
||||
Intent alarm = new Intent(context, ServiceSynchronize.class);
|
||||
alarm.setAction("alarm");
|
||||
PendingIntent piAlarm = PendingIntent.getService(context, PI_ALARM, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
am.cancel(piAlarm);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!prefs.getBoolean("schedule", false))
|
||||
return;
|
||||
|
||||
int minuteStart = prefs.getInt("schedule_start", 0);
|
||||
int minuteEnd = prefs.getInt("schedule_end", 0);
|
||||
|
||||
if (minuteEnd <= minuteStart)
|
||||
minuteEnd += 24 * 60;
|
||||
|
||||
Calendar calStart = Calendar.getInstance();
|
||||
calStart.set(Calendar.HOUR_OF_DAY, minuteStart / 60);
|
||||
calStart.set(Calendar.MINUTE, minuteStart % 60);
|
||||
calStart.set(Calendar.SECOND, 0);
|
||||
calStart.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Calendar calEnd = Calendar.getInstance();
|
||||
calEnd.set(Calendar.HOUR_OF_DAY, minuteEnd / 60);
|
||||
calEnd.set(Calendar.MINUTE, minuteEnd % 60);
|
||||
calEnd.set(Calendar.SECOND, 0);
|
||||
calEnd.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
long now = new Date().getTime();
|
||||
if (now > calEnd.getTimeInMillis()) {
|
||||
calStart.set(Calendar.DAY_OF_MONTH, calStart.get(Calendar.DAY_OF_MONTH) + 1);
|
||||
calEnd.set(Calendar.DAY_OF_MONTH, calEnd.get(Calendar.DAY_OF_MONTH) + 1);
|
||||
}
|
||||
|
||||
long start = calStart.getTimeInMillis();
|
||||
long end = calEnd.getTimeInMillis();
|
||||
long next = (now < start ? start : end);
|
||||
|
||||
Log.i("Schedule now=" + new Date(now));
|
||||
Log.i("Schedule start=" + new Date(start));
|
||||
Log.i("Schedule end=" + new Date(end));
|
||||
Log.i("Schedule next=" + new Date(next));
|
||||
|
||||
boolean enabled = (now >= start && now < end);
|
||||
prefs.edit().putBoolean("enabled", enabled).apply();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, next, piAlarm);
|
||||
else
|
||||
am.set(AlarmManager.RTC_WAKEUP, next, piAlarm);
|
||||
}
|
||||
|
||||
public static void schedule(Context context) {
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("schedule"));
|
||||
static void boot(final Context context) {
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
// Restore snooze timers
|
||||
for (EntityMessage message : db.message().getSnoozed())
|
||||
EntityMessage.snooze(context, message.id, message.ui_snoozed);
|
||||
|
||||
// Restore schedule
|
||||
schedule(context);
|
||||
|
||||
// Conditionally init service
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
|
||||
int accounts = db.account().getSynchronizingAccounts(false).size();
|
||||
|
||||
if (enabled && accounts > 0)
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("init"));
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void reload(Context context, String reason) {
|
||||
static void reschedule(Context context) {
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("alarm"));
|
||||
}
|
||||
|
||||
static void reload(Context context, String reason) {
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("reload")
|
||||
|
||||
Reference in New Issue
Block a user