diff --git a/app/src/main/java/eu/faircode/email/FragmentFolders.java b/app/src/main/java/eu/faircode/email/FragmentFolders.java index 96f487bf3d..68536333f0 100644 --- a/app/src/main/java/eu/faircode/email/FragmentFolders.java +++ b/app/src/main/java/eu/faircode/email/FragmentFolders.java @@ -304,7 +304,7 @@ public class FragmentFolders extends FragmentBase { // Folder list EntityAccount account = db.account().getAccount(aid); if (account != null && !"connected".equals(account.state)) - ServiceUI.fsync(context, aid); + WorkerFolderSync.queue(aid); else ServiceSynchronize.reload(getContext(), "refresh folders"); } diff --git a/app/src/main/java/eu/faircode/email/ServiceUI.java b/app/src/main/java/eu/faircode/email/ServiceUI.java index 2e4d08a3b4..f3450955ec 100644 --- a/app/src/main/java/eu/faircode/email/ServiceUI.java +++ b/app/src/main/java/eu/faircode/email/ServiceUI.java @@ -9,13 +9,9 @@ import android.net.Uri; import android.os.PowerManager; import android.preference.PreferenceManager; -import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.Properties; -import javax.mail.MessagingException; -import javax.mail.Session; import javax.mail.Store; import androidx.annotation.Nullable; @@ -135,10 +131,6 @@ public class ServiceUI extends IntentService { onSnooze(id); break; - case "fsync": - onFolderSync(id); - break; - default: Log.w("Unknown action: " + parts[0]); } @@ -266,71 +258,4 @@ public class ServiceUI extends IntentService { db.endTransaction(); } } - - private void onFolderSync(long aid) { - DB db = DB.getInstance(this); - EntityAccount account = db.account().getAccount(aid); - if (account == null) - return; - - Store istore = null; - try { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean debug = (prefs.getBoolean("debug", false) || BuildConfig.BETA_RELEASE); - - String protocol = account.getProtocol(); - - // Get properties - Properties props = MessageHelper.getSessionProperties(account.auth_type, account.realm, account.insecure); - props.put("mail." + protocol + ".separatestoreconnection", "true"); - - // Create session - final Session isession = Session.getInstance(props, null); - isession.setDebug(debug); - - // Connect account - Log.i(account.name + " connecting"); - db.account().setAccountState(account.id, "connecting"); - istore = isession.getStore(protocol); - Helper.connect(this, istore, account); - db.account().setAccountState(account.id, "connected"); - db.account().setAccountConnected(account.id, new Date().getTime()); - db.account().setAccountError(account.id, null); - Log.i(account.name + " connected"); - - // Synchronize folders - Core.onSynchronizeFolders(this, account, istore, new Core.State()); - - } catch (Throwable ex) { - Log.w(ex); - Core.reportError(this, account, null, ex); - db.account().setAccountError(account.id, Helper.formatThrowable(ex)); - } finally { - if (istore != null) { - Log.i(account.name + " closing"); - db.account().setAccountState(account.id, "closing"); - - try { - istore.close(); - } catch (MessagingException ex) { - Log.e(ex); - } - - Log.i(account.name + " closed"); - } - - db.account().setAccountState(account.id, null); - } - } - - public static void fsync(Context context, long account) { - try { - context.startService( - new Intent(context, ServiceUI.class) - .setAction("fsync:" + account)); - } catch (IllegalStateException ex) { - Log.w(ex); - // The user went away - } - } } diff --git a/app/src/main/java/eu/faircode/email/WorkerFolderSync.java b/app/src/main/java/eu/faircode/email/WorkerFolderSync.java new file mode 100644 index 0000000000..2812da670b --- /dev/null +++ b/app/src/main/java/eu/faircode/email/WorkerFolderSync.java @@ -0,0 +1,111 @@ +package eu.faircode.email; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import java.util.Date; +import java.util.Properties; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Store; + +import androidx.annotation.NonNull; +import androidx.work.Data; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkInfo; +import androidx.work.WorkManager; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +public class WorkerFolderSync extends Worker { + public WorkerFolderSync(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + } + + @NonNull + @Override + public Result doWork() { + long aid = getInputData().getLong("account", -1); + Log.i("Work account=" + aid); + + DB db = DB.getInstance(getApplicationContext()); + EntityAccount account = db.account().getAccount(aid); + if (account == null) + return Result.success(); + + Store istore = null; + try { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + boolean debug = (prefs.getBoolean("debug", false) || BuildConfig.BETA_RELEASE); + + String protocol = account.getProtocol(); + + // Get properties + Properties props = MessageHelper.getSessionProperties(account.auth_type, account.realm, account.insecure); + props.put("mail." + protocol + ".separatestoreconnection", "true"); + + // Create session + Session isession = Session.getInstance(props, null); + isession.setDebug(debug); + + // Connect account + Log.i(account.name + " connecting"); + db.account().setAccountState(account.id, "connecting"); + istore = isession.getStore(protocol); + Helper.connect(getApplicationContext(), istore, account); + db.account().setAccountState(account.id, "connected"); + db.account().setAccountConnected(account.id, new Date().getTime()); + db.account().setAccountError(account.id, null); + Log.i(account.name + " connected"); + + // Synchronize folders + Core.onSynchronizeFolders(getApplicationContext(), account, istore, new Core.State()); + + } catch (Throwable ex) { + Log.w(ex); + Core.reportError(getApplicationContext(), account, null, ex); + db.account().setAccountError(account.id, Helper.formatThrowable(ex)); + } finally { + if (istore != null) + try { + Log.i(account.name + " closing"); + db.account().setAccountState(account.id, "closing"); + istore.close(); + } catch (MessagingException ex) { + Log.e(ex); + } finally { + Log.i(account.name + " closed"); + db.account().setAccountState(account.id, null); + } + } + + return Result.success(); + } + + static void queue(long aid) { + String tag = "fsync:" + aid; + Log.i("Queuing work " + tag); + + try { + for (WorkInfo info : WorkManager.getInstance().getWorkInfosByTag(tag).get()) + if (!info.getState().isFinished()) { + Log.i("Work already queued " + tag); + return; + } + } catch (Throwable ex) { + Log.w(ex); + } + + Data data = new Data.Builder().putLong("account", aid).build(); + OneTimeWorkRequest workRequest = + new OneTimeWorkRequest.Builder(WorkerFolderSync.class) + .addTag(tag) + .setInputData(data) + .build(); + WorkManager.getInstance().enqueue(workRequest); + + Log.i("Queued work " + tag); + } +}