From ff0e5641fce422a94653b60e061f27c8e22acca6 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 12 Jan 2020 15:38:00 +0100 Subject: [PATCH] Replace work manager by alarm for polling --- .../java/eu/faircode/email/ActivityView.java | 13 +-- .../eu/faircode/email/ServiceExternal.java | 41 ++++--- .../eu/faircode/email/ServiceSynchronize.java | 2 +- .../eu/faircode/email/ServiceTileUnseen.java | 9 +- .../java/eu/faircode/email/ServiceUI.java | 66 ++++++++++- .../java/eu/faircode/email/WorkerPoll.java | 108 ------------------ 6 files changed, 92 insertions(+), 147 deletions(-) delete mode 100644 app/src/main/java/eu/faircode/email/WorkerPoll.java diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index a3668f592f..62b840f7d4 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -820,18 +820,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB intent.removeExtra("refresh"); setIntent(intent); - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - WorkerPoll.sync(context, null); - return null; - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getSupportFragmentManager(), ex); - } - }.execute(this, new Bundle(), "view:refresh"); + ServiceUI.sync(this, null); } String action = intent.getAction(); diff --git a/app/src/main/java/eu/faircode/email/ServiceExternal.java b/app/src/main/java/eu/faircode/email/ServiceExternal.java index c9be31bc59..d18128af9d 100644 --- a/app/src/main/java/eu/faircode/email/ServiceExternal.java +++ b/app/src/main/java/eu/faircode/email/ServiceExternal.java @@ -29,6 +29,8 @@ import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.preference.PreferenceManager; +import java.util.Collections; +import java.util.List; import java.util.concurrent.ExecutorService; public class ServiceExternal extends Service { @@ -82,32 +84,37 @@ public class ServiceExternal extends Service { enabled = true; else if (ACTION_DISABLE.equals(action)) enabled = false; - else + else // poll enabled = null; executor.submit(new Runnable() { @Override public void run() { - if (accountName == null) { - if (enabled == null) - WorkerPoll.sync(context, null); - else { + DB db = DB.getInstance(context); + + if (enabled == null) { + List accounts = db.account().getSynchronizingAccounts(); + for (EntityAccount account : accounts) + if (accountName == null || accountName.equals(account.name)) { + List folders = db.folder().getSynchronizingFolders(account.id); + if (folders.size() > 0) + Collections.sort(folders, folders.get(0).getComparator(context)); + for (EntityFolder folder : folders) + EntityOperation.sync(context, folder.id, false); + } + ServiceSynchronize.eval(context, "external poll account=" + accountName); + } else { + if (accountName == null) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit().putBoolean("enabled", enabled).apply(); ServiceSynchronize.eval(context, "external enabled=" + enabled); - } - } else { - DB db = DB.getInstance(context); + } else { + EntityAccount account = db.account().getAccount(accountName); + if (account == null) { + EntityLog.log(context, "Account not found name=" + accountName); + return; + } - EntityAccount account = db.account().getAccount(accountName); - if (account == null) { - EntityLog.log(context, "Account not found name=" + accountName); - return; - } - - if (enabled == null) - WorkerPoll.sync(context, account.id); - else { db.account().setAccountSynchronize(account.id, enabled); ServiceSynchronize.eval(context, "external account=" + accountName + " enabled=" + enabled); } diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index a9b4a4c938..1ae4cca832 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -1573,7 +1573,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, pi); } - WorkerPoll.init(context, enabled); + ServiceUI.schedule(context, enabled); } private static long[] getSchedule(Context context) { diff --git a/app/src/main/java/eu/faircode/email/ServiceTileUnseen.java b/app/src/main/java/eu/faircode/email/ServiceTileUnseen.java index b7b19062ba..433c9390d7 100644 --- a/app/src/main/java/eu/faircode/email/ServiceTileUnseen.java +++ b/app/src/main/java/eu/faircode/email/ServiceTileUnseen.java @@ -20,7 +20,6 @@ package eu.faircode.email; */ import android.annotation.TargetApi; -import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.os.Build; @@ -97,12 +96,6 @@ public class ServiceTileUnseen extends TileService { public void onClick() { Log.i("Click tile unseen"); - final Context context = getApplicationContext(); - new Thread(new Runnable() { - @Override - public void run() { - WorkerPoll.sync(context, null); - } - }).start(); + ServiceUI.sync(this, null); } } diff --git a/app/src/main/java/eu/faircode/email/ServiceUI.java b/app/src/main/java/eu/faircode/email/ServiceUI.java index 7e2a152905..4914e4bc41 100644 --- a/app/src/main/java/eu/faircode/email/ServiceUI.java +++ b/app/src/main/java/eu/faircode/email/ServiceUI.java @@ -19,8 +19,10 @@ package eu.faircode.email; Copyright 2018-2020 by Marcel Bokhorst (M66B) */ +import android.app.AlarmManager; import android.app.IntentService; import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -28,10 +30,12 @@ import android.os.Bundle; import android.widget.Toast; import androidx.annotation.Nullable; +import androidx.core.app.AlarmManagerCompat; import androidx.core.app.RemoteInput; import androidx.preference.PreferenceManager; import java.io.IOException; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.regex.Pattern; @@ -52,7 +56,8 @@ public class ServiceUI extends IntentService { static final int PI_IGNORED = 10; static final int PI_THREAD = 11; static final int PI_WAKEUP = 12; - static final int PI_BANNER = 13; + static final int PI_SYNC = 13; + static final int PI_BANNER = 14; public ServiceUI() { this(ServiceUI.class.getName()); @@ -153,6 +158,11 @@ public class ServiceUI extends IntentService { onWakeup(id); break; + case "sync": + boolean reschedule = intent.getBooleanExtra("reschedule", false); + onSync(id, reschedule); + break; + case "daily": case "banner": onBanner(); @@ -429,8 +439,62 @@ public class ServiceUI extends IntentService { ServiceSynchronize.eval(ServiceUI.this, "wakeup"); } + private void onSync(long aid, boolean reschedule) { + DB db = DB.getInstance(this); + try { + db.beginTransaction(); + + List accounts = db.account().getSynchronizingAccounts(); + for (EntityAccount account : accounts) + if (aid < 0 || account.id.equals(aid)) { + List folders = db.folder().getSynchronizingFolders(account.id); + if (folders.size() > 0) + Collections.sort(folders, folders.get(0).getComparator(this)); + for (EntityFolder folder : folders) + EntityOperation.sync(this, folder.id, false); + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + if (reschedule) + schedule(this, true); + + ServiceSynchronize.eval(this, "poll"); + } + private void onBanner() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.edit().remove("banner").apply(); } + + static void sync(Context context, Long account) { + context.startService(new Intent(context, ServiceUI.class) + .setAction(account == null ? "sync" : "sync:" + account)); + } + + static void schedule(Context context, boolean enabled) { + Intent intent = new Intent(context, ServiceUI.class); + intent.setAction("sync"); + intent.putExtra("reschedule", true); + PendingIntent piSync = PendingIntent.getService( + context, ServiceUI.PI_SYNC, intent, PendingIntent.FLAG_UPDATE_CURRENT); + + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + am.cancel(piSync); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + int pollInterval = prefs.getInt("poll_interval", 0); + if (enabled && pollInterval > 0) { + long now = new Date().getTime(); + long interval = pollInterval * 60 * 1000L; + long next = now + interval - now % interval; + + Log.i("Poll next=" + new Date(next)); + + AlarmManagerCompat.setAndAllowWhileIdle(am, AlarmManager.RTC_WAKEUP, next, piSync); + } + } } diff --git a/app/src/main/java/eu/faircode/email/WorkerPoll.java b/app/src/main/java/eu/faircode/email/WorkerPoll.java deleted file mode 100644 index 050acc3fec..0000000000 --- a/app/src/main/java/eu/faircode/email/WorkerPoll.java +++ /dev/null @@ -1,108 +0,0 @@ -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-2020 by Marcel Bokhorst (M66B) -*/ - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.annotation.NonNull; -import androidx.preference.PreferenceManager; -import androidx.work.ExistingPeriodicWorkPolicy; -import androidx.work.PeriodicWorkRequest; -import androidx.work.WorkManager; -import androidx.work.Worker; -import androidx.work.WorkerParameters; - -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class WorkerPoll extends Worker { - public WorkerPoll(@NonNull Context context, @NonNull WorkerParameters workerParams) { - super(context, workerParams); - Log.i("Instance " + getName()); - } - - @NonNull - @Override - public Result doWork() { - Log.i("Running " + getName()); - - sync(getApplicationContext(), null); - - return Result.success(); - } - - static void init(Context context, boolean enabled) { - try { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - int pollInterval = prefs.getInt("poll_interval", 0); - if (enabled && pollInterval > 0) { - int min = (int) (new Date().getTime() / (60 * 1000L)); - int delay = pollInterval - (min % pollInterval) + pollInterval; - Log.i("Queuing " + getName() + " every " + pollInterval + " minutes delay=" + delay); - - PeriodicWorkRequest workRequest = - new PeriodicWorkRequest.Builder(WorkerPoll.class, pollInterval, TimeUnit.MINUTES) - .setInitialDelay(delay, TimeUnit.MINUTES) - .build(); - WorkManager.getInstance(context) - .enqueueUniquePeriodicWork(getName(), ExistingPeriodicWorkPolicy.REPLACE, workRequest); - - Log.i("Queued " + getName()); - } else { - Log.i("Cancelling " + getName()); - WorkManager.getInstance(context).cancelUniqueWork(getName()); - Log.i("Cancelled " + getName()); - } - } catch (IllegalStateException ex) { - // https://issuetracker.google.com/issues/138465476 - Log.w(ex); - } - } - - static void sync(Context context, Long aid) { - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - List accounts = db.account().getSynchronizingAccounts(); - for (EntityAccount account : accounts) - if (aid == null || account.id.equals(aid)) { - List folders = db.folder().getSynchronizingFolders(account.id); - if (folders.size() > 0) - Collections.sort(folders, folders.get(0).getComparator(context)); - for (EntityFolder folder : folders) - EntityOperation.sync(context, folder.id, false); - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - ServiceSynchronize.eval(context, "refresh/poll"); - } - - private static String getName() { - return WorkerPoll.class.getSimpleName(); - } -}