mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-07 09:33:39 +02:00
Replaced foreground operations by oneshot mode
This commit is contained in:
@@ -361,13 +361,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
|
||||
}
|
||||
});
|
||||
|
||||
db.message().liveUnseenNotify().observe(this, new Observer<List<TupleMessageEx>>() {
|
||||
@Override
|
||||
public void onChanged(List<TupleMessageEx> messages) {
|
||||
Core.notifyMessages(ActivityView.this, messages);
|
||||
}
|
||||
});
|
||||
|
||||
if (getSupportFragmentManager().getFragments().size() == 0 && !getIntent().hasExtra(Intent.EXTRA_PROCESS_TEXT))
|
||||
init();
|
||||
|
||||
|
||||
@@ -133,8 +133,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
|
||||
vwLevel.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
if (folder.sync_state == null ||
|
||||
"requested".equals(folder.sync_state) || "manual".equals(folder.sync_state)) {
|
||||
if (folder.sync_state == null || "requested".equals(folder.sync_state)) {
|
||||
if ("waiting".equals(folder.state))
|
||||
ivState.setImageResource(R.drawable.baseline_hourglass_empty_24);
|
||||
else if ("connected".equals(folder.state))
|
||||
|
||||
@@ -260,12 +260,6 @@ class Core {
|
||||
}
|
||||
}
|
||||
|
||||
if (EntityOperation.SYNC.equals(op.name) && jargs.getBoolean(3) /* foreground */) {
|
||||
Log.w("Deleting foreground SYNC");
|
||||
db.operation().deleteOperation(op.id);
|
||||
db.folder().setFolderSyncState(folder.id, null);
|
||||
}
|
||||
|
||||
throw ex;
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -27,10 +27,8 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -84,9 +82,6 @@ public class EntityOperation {
|
||||
static final String ATTACHMENT = "attachment";
|
||||
static final String SYNC = "sync";
|
||||
|
||||
// These operations should be prepared to be executed twice by both the background and foreground sync
|
||||
private static List<String> FOREGROUND = Arrays.asList(KEYWORD, HEADERS, RAW, BODY, ATTACHMENT);
|
||||
|
||||
static void queue(Context context, DB db, EntityMessage message, String name, Object... values) {
|
||||
JSONArray jargs = new JSONArray();
|
||||
for (Object value : values)
|
||||
@@ -214,46 +209,37 @@ public class EntityOperation {
|
||||
|
||||
if (SEND.equals(name))
|
||||
ServiceSend.start(context);
|
||||
else if (FOREGROUND.contains(name)) {
|
||||
EntityAccount account = db.account().getAccount(message.account);
|
||||
if (account != null && !"connected".equals(account.state))
|
||||
WorkerOperations.queue(operation.folder);
|
||||
}
|
||||
else
|
||||
ServiceSynchronize.process(context);
|
||||
}
|
||||
|
||||
static void sync(Context context, long fid, boolean foreground) {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
EntityFolder folder = db.folder().getFolder(fid);
|
||||
EntityAccount account = null;
|
||||
if (folder.account != null)
|
||||
account = db.account().getAccount(folder.account);
|
||||
|
||||
if (db.operation().getOperationCount(fid, EntityOperation.SYNC) == 0) {
|
||||
|
||||
EntityFolder folder = db.folder().getFolder(fid);
|
||||
EntityAccount account = null;
|
||||
if (folder.account != null)
|
||||
account = db.account().getAccount(folder.account);
|
||||
|
||||
JSONArray jargs = folder.getSyncArgs();
|
||||
jargs.put(foreground);
|
||||
|
||||
EntityOperation operation = new EntityOperation();
|
||||
operation.folder = folder.id;
|
||||
operation.message = null;
|
||||
operation.name = SYNC;
|
||||
operation.args = jargs.toString();
|
||||
operation.args = folder.getSyncArgs().toString();
|
||||
operation.created = new Date().getTime();
|
||||
operation.id = db.operation().insertOperation(operation);
|
||||
|
||||
if (account != null && !"connected".equals(account.state)) {
|
||||
db.folder().setFolderState(fid, "waiting");
|
||||
db.folder().setFolderSyncState(fid, "manual");
|
||||
} else
|
||||
db.folder().setFolderSyncState(fid, "requested");
|
||||
|
||||
if (account == null) // Outbox
|
||||
ServiceSend.start(context);
|
||||
else if (foreground && !"connected".equals(account.state))
|
||||
WorkerOperations.queue(fid);
|
||||
|
||||
Log.i("Queued sync folder=" + folder + " foreground=" + foreground);
|
||||
Log.i("Queued sync folder=" + folder);
|
||||
}
|
||||
|
||||
if (foreground)
|
||||
db.folder().setFolderSyncState(fid, "requested");
|
||||
|
||||
if (account == null) // Outbox
|
||||
ServiceSend.start(context);
|
||||
else if (foreground)
|
||||
ServiceSynchronize.process(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -302,11 +302,12 @@ public class FragmentFolders extends FragmentBase {
|
||||
EntityOperation.sync(context, folder.id, true);
|
||||
} else {
|
||||
// Folder list
|
||||
EntityAccount account = db.account().getAccount(aid);
|
||||
if (account != null && !"connected".equals(account.state))
|
||||
WorkerFolderSync.queue(aid);
|
||||
else
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
if (enabled)
|
||||
ServiceSynchronize.reload(getContext(), "refresh folders");
|
||||
else
|
||||
ServiceSynchronize.process(context);
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
|
||||
@@ -1438,8 +1438,6 @@ public class FragmentMessages extends FragmentBase {
|
||||
for (String name : values.keySet())
|
||||
outState.putLongArray("fair:name:" + name, Helper.toLongArray(values.get(name)));
|
||||
|
||||
outState.putBoolean("fair:refreshing", swipeRefresh.isRefreshing());
|
||||
|
||||
if (rvMessage != null) {
|
||||
Parcelable rv = rvMessage.getLayoutManager().onSaveInstanceState();
|
||||
outState.putParcelable("fair:rv", rv);
|
||||
@@ -1464,8 +1462,6 @@ public class FragmentMessages extends FragmentBase {
|
||||
values.get(name).add(value);
|
||||
}
|
||||
|
||||
swipeRefresh.setRefreshing(savedInstanceState.getBoolean("fair:refreshing"));
|
||||
|
||||
if (rvMessage != null) {
|
||||
Parcelable rv = savedInstanceState.getBundle("fair:rv");
|
||||
rvMessage.getLayoutManager().onRestoreInstanceState(rv);
|
||||
@@ -1519,6 +1515,7 @@ public class FragmentMessages extends FragmentBase {
|
||||
public void onChanged(List<TupleFolderEx> folders) {
|
||||
if (folders == null)
|
||||
folders = new ArrayList<>();
|
||||
Log.i("Folder state updated count=" + folders.size());
|
||||
|
||||
int unseen = 0;
|
||||
boolean errors = false;
|
||||
@@ -1536,7 +1533,7 @@ public class FragmentMessages extends FragmentBase {
|
||||
|
||||
boolean refreshing = false;
|
||||
for (TupleFolderEx folder : folders)
|
||||
if (folder.isSynchronizing()) {
|
||||
if (folder.sync_state != null) {
|
||||
refreshing = true;
|
||||
break;
|
||||
}
|
||||
@@ -1559,6 +1556,7 @@ public class FragmentMessages extends FragmentBase {
|
||||
db.folder().liveFolderEx(folder).observe(getViewLifecycleOwner(), new Observer<TupleFolderEx>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable TupleFolderEx folder) {
|
||||
Log.i("Folder state updated");
|
||||
if (folder == null)
|
||||
setSubtitle(null);
|
||||
else {
|
||||
@@ -1575,7 +1573,7 @@ public class FragmentMessages extends FragmentBase {
|
||||
}
|
||||
}
|
||||
|
||||
boolean refreshing = (folder != null && folder.isSynchronizing());
|
||||
boolean refreshing = (folder != null && folder.sync_state != null);
|
||||
|
||||
if (!refreshing && manual) {
|
||||
manual = false;
|
||||
|
||||
@@ -41,9 +41,6 @@ import com.sun.mail.imap.IMAPFolder;
|
||||
import com.sun.mail.imap.IMAPMessage;
|
||||
import com.sun.mail.imap.IMAPStore;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -100,9 +97,11 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
private static final long RECONNECT_BACKOFF = 90 * 1000L; // milliseconds
|
||||
private static final int ACCOUNT_ERROR_AFTER = 90; // minutes
|
||||
private static final int BACKOFF_ERROR_AFTER = 16; // seconds
|
||||
private static final long ONESHOT_DURATION = 60 * 1000L; // milliseconds
|
||||
private static final long STOP_DELAY = 5000L; // milliseconds
|
||||
|
||||
static final int PI_ALARM = 1;
|
||||
static final int PI_ONESHOT = 2;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -184,6 +183,14 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
serviceManager.service_reload(intent.getStringExtra("reason"));
|
||||
break;
|
||||
|
||||
case "oneshot_start":
|
||||
serviceManager.service_oneshot(true);
|
||||
break;
|
||||
|
||||
case "oneshot_end":
|
||||
serviceManager.service_oneshot(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.w("Unknown action: " + action);
|
||||
}
|
||||
@@ -924,7 +931,9 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
|
||||
private boolean isEnabled() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
return prefs.getBoolean("enabled", true);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
boolean oneshot = prefs.getBoolean("oneshot", false);
|
||||
return (enabled || oneshot);
|
||||
}
|
||||
|
||||
private void service_init() {
|
||||
@@ -947,6 +956,32 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
}
|
||||
}
|
||||
|
||||
private void service_oneshot(boolean start) {
|
||||
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent alarm = new Intent(ServiceSynchronize.this, ServiceSynchronize.class);
|
||||
alarm.setAction("oneshot_end");
|
||||
PendingIntent piOneshot;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
piOneshot = PendingIntent.getService(ServiceSynchronize.this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
else
|
||||
piOneshot = PendingIntent.getForegroundService(ServiceSynchronize.this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
am.cancel(piOneshot);
|
||||
|
||||
if (start) {
|
||||
// Network events will manage the service
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
||||
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
else
|
||||
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
} else {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
prefs.edit().putBoolean("oneshot", false).apply();
|
||||
queue_reload(false, "oneshot");
|
||||
}
|
||||
}
|
||||
|
||||
private void service_destroy() {
|
||||
synchronized (this) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service destroy");
|
||||
@@ -1105,21 +1140,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
Thread.sleep(STOP_DELAY);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
if (queued == 0 && !isEnabled()) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service stop");
|
||||
List<EntityOperation> ops = db.operation().getOperations(EntityOperation.SYNC);
|
||||
for (EntityOperation op : ops)
|
||||
try {
|
||||
JSONArray jargs = new JSONArray(op.args);
|
||||
if (!jargs.getBoolean(3) /* foreground */) {
|
||||
Log.i("Deleting bacground SYNC args=" + jargs);
|
||||
db.operation().deleteOperation(op.id);
|
||||
}
|
||||
} catch (JSONException ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
if (queued == 0 && !isEnabled())
|
||||
stopService();
|
||||
}
|
||||
|
||||
wl.release();
|
||||
@@ -1127,12 +1149,27 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void stopService() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service stop");
|
||||
|
||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
List<EntityOperation> ops = db.operation().getOperations(EntityOperation.SYNC);
|
||||
for (EntityOperation op : ops)
|
||||
db.folder().setFolderSyncState(op.folder, null);
|
||||
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
PendingIntent piAlarm;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
piAlarm = PendingIntent.getService(context, PI_ALARM, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
else
|
||||
piAlarm = PendingIntent.getForegroundService(context, PI_ALARM, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
am.cancel(piAlarm);
|
||||
@@ -1193,6 +1230,18 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
try {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
// Reset state
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().remove("oneshot").apply();
|
||||
|
||||
for (EntityAccount account : db.account().getAccounts())
|
||||
db.account().setAccountState(account.id, null);
|
||||
|
||||
for (EntityFolder folder : db.folder().getFolders()) {
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
db.folder().setFolderSyncState(folder.id, null);
|
||||
}
|
||||
|
||||
// Restore snooze timers
|
||||
for (EntityMessage message : db.message().getSnoozed())
|
||||
EntityMessage.snooze(context, message.id, message.ui_snoozed);
|
||||
@@ -1201,11 +1250,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
schedule(context);
|
||||
|
||||
// Conditionally init service
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
|
||||
int accounts = db.account().getSynchronizingAccounts().size();
|
||||
|
||||
if (enabled && accounts > 0)
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
@@ -1231,4 +1277,16 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
.setAction("reload")
|
||||
.putExtra("reason", reason));
|
||||
}
|
||||
|
||||
static void process(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
boolean oneshot = prefs.getBoolean("oneshot", false);
|
||||
if (!enabled && !oneshot) {
|
||||
prefs.edit().putBoolean("oneshot", true).apply();
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("oneshot_start"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,13 +29,6 @@ public class TupleFolderEx extends EntityFolder {
|
||||
public int content;
|
||||
public int unseen;
|
||||
|
||||
boolean isSynchronizing() {
|
||||
return (sync_state != null &&
|
||||
(EntityFolder.OUTBOX.equals(type) ||
|
||||
!"requested".equals(sync_state) ||
|
||||
"connected".equals(accountState)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof TupleFolderEx) {
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
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.Session;
|
||||
import javax.mail.Store;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
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 (Throwable 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 = WorkerFolderSync.class.getSimpleName() + ":" + aid;
|
||||
Log.i("Queuing " + tag);
|
||||
|
||||
Data data = new Data.Builder().putLong("account", aid).build();
|
||||
OneTimeWorkRequest workRequest =
|
||||
new OneTimeWorkRequest.Builder(WorkerFolderSync.class)
|
||||
.addTag(tag)
|
||||
.setInputData(data)
|
||||
.build();
|
||||
WorkManager.getInstance().enqueueUniqueWork(tag, ExistingWorkPolicy.KEEP, workRequest);
|
||||
|
||||
Log.i("Queued " + tag);
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
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.Folder;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.event.StoreEvent;
|
||||
import javax.mail.event.StoreListener;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
|
||||
public class WorkerOperations extends Worker {
|
||||
public WorkerOperations(@NonNull Context context, @NonNull WorkerParameters args) {
|
||||
super(context, args);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result doWork() {
|
||||
long fid = getInputData().getLong("folder", -1);
|
||||
Log.i("Work folder=" + fid);
|
||||
|
||||
final DB db = DB.getInstance(getApplicationContext());
|
||||
|
||||
final EntityFolder folder = db.folder().getFolder(fid);
|
||||
if (folder == null)
|
||||
return Result.success();
|
||||
final EntityAccount account = db.account().getAccount(folder.account);
|
||||
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");
|
||||
|
||||
// Listen for store events
|
||||
istore.addStoreListener(new StoreListener() {
|
||||
@Override
|
||||
public void notification(StoreEvent e) {
|
||||
if (e.getMessageType() == StoreEvent.ALERT) {
|
||||
db.account().setAccountError(account.id, e.getMessage());
|
||||
Core.reportError(
|
||||
getApplicationContext(), account, null,
|
||||
new Core.AlertException(e.getMessage()));
|
||||
} else
|
||||
Log.i(account.name + " notice: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
// Connect folder
|
||||
Log.i(folder.name + " connecting");
|
||||
db.folder().setFolderState(folder.id, "connecting");
|
||||
Folder ifolder = istore.getFolder(folder.name);
|
||||
ifolder.open(Folder.READ_WRITE);
|
||||
db.folder().setFolderState(folder.id, "connected");
|
||||
db.folder().setFolderError(folder.id, null);
|
||||
Log.i(folder.name + " connected");
|
||||
|
||||
// Process operations
|
||||
Core.processOperations(getApplicationContext(), account, folder, isession, istore, ifolder, new Core.State());
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
Core.reportError(getApplicationContext(), account, folder, ex);
|
||||
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
||||
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, false));
|
||||
} finally {
|
||||
if (istore != null)
|
||||
try {
|
||||
Log.i(account.name + " closing");
|
||||
db.account().setAccountState(account.id, "closing");
|
||||
db.folder().setFolderState(folder.id, "closing");
|
||||
istore.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
} finally {
|
||||
Log.i(account.name + " closed");
|
||||
db.account().setAccountState(account.id, "closed");
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
db.folder().setFolderSyncState(folder.id, null);
|
||||
}
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
static void queue(long fid) {
|
||||
String tag = WorkerOperations.class.getSimpleName() + ":" + fid;
|
||||
Log.i("Queuing " + tag);
|
||||
|
||||
Data data = new Data.Builder().putLong("folder", fid).build();
|
||||
OneTimeWorkRequest workRequest =
|
||||
new OneTimeWorkRequest.Builder(WorkerOperations.class)
|
||||
.addTag(tag)
|
||||
.setInputData(data)
|
||||
.build();
|
||||
WorkManager.getInstance().enqueueUniqueWork(tag, ExistingWorkPolicy.KEEP, workRequest);
|
||||
|
||||
Log.i("Queued " + tag);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user