Use foreground worker

pull/152/head
M66B 5 years ago
parent 4ada53ff0f
commit d7e7371603

@ -109,6 +109,7 @@ dependencies {
def lifecycle_version = "2.0.0"
def room_version = "2.0.0"
def paging_version = "2.1.0"
def work_version = "1.0.0-rc02"
def billingclient_version = "1.2"
def javamail_version = "1.6.3"
def jsoup_version = "1.11.3"
@ -150,6 +151,9 @@ dependencies {
// https://mvnrepository.com/artifact/androidx.paging/paging-runtime
implementation "androidx.paging:paging-runtime:$paging_version"
// https://mvnrepository.com/artifact/android.arch.work/work-runtime
implementation "android.arch.work:work-runtime:$work_version"
// https://developer.android.com/google/play/billing/billing_library_releases_notes
implementation "com.android.billingclient:billing:$billingclient_version"

@ -215,7 +215,7 @@ public class EntityOperation {
else if (FOREGROUND.contains(name)) {
EntityAccount account = db.account().getAccount(message.account);
if (account != null && !"connected".equals(account.state))
ServiceUI.process(context, operation.folder);
WorkerForeground.queue(operation.folder);
}
}
@ -248,7 +248,7 @@ public class EntityOperation {
if (account == null) // Outbox
ServiceSend.start(context);
else if (foreground && !"connected".equals(account.state))
ServiceUI.process(context, fid);
WorkerForeground.queue(fid);
Log.i("Queued sync folder=" + folder + " foreground=" + foreground);
}

@ -259,17 +259,14 @@ public class ServiceSynchronize extends LifecycleService {
public void notification(StoreEvent e) {
try {
wlAccount.acquire();
String type = (e.getMessageType() == StoreEvent.ALERT ? "alert" : "notice");
if (e.getMessageType() == StoreEvent.ALERT) {
Log.w(account.name + " " + type + ": " + e.getMessage());
EntityLog.log(ServiceSynchronize.this, account.name + " " + type + ": " + e.getMessage());
db.account().setAccountError(account.id, e.getMessage());
Core.reportError(
ServiceSynchronize.this, account, null,
new Core.AlertException(e.getMessage()));
state.error();
} else
Log.i(account.name + " " + type + ": " + e.getMessage());
Log.i(account.name + " notice: " + e.getMessage());
} finally {
wlAccount.release();
}

@ -14,7 +14,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
@ -136,10 +135,6 @@ public class ServiceUI extends IntentService {
onSnooze(id);
break;
case "process":
onProcessOperations(id);
break;
case "fsync":
onFolderSync(id);
break;
@ -272,80 +267,6 @@ public class ServiceUI extends IntentService {
}
}
private void onProcessOperations(long fid) {
DB db = DB.getInstance(this);
EntityFolder folder = db.folder().getFolder(fid);
if (folder == null)
return;
EntityAccount account = db.account().getAccount(folder.account);
if (account == null)
return;
Folder ifolder = 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);
Store istore = accountStore.get(account.id);
if (istore == null || !istore.isConnected()) {
// 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");
accountStore.put(account, istore);
} else
Log.i(account + " reusing connection");
// Connect folder
Log.i(folder.name + " connecting");
db.folder().setFolderState(folder.id, "connecting");
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(this, account, folder, isession, istore, ifolder, new Core.State());
} catch (Throwable ex) {
Log.w(ex);
Core.reportError(this, account, folder, ex);
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, false));
} finally {
if (ifolder != null)
try {
Log.i(folder.name + " closing");
db.folder().setFolderState(folder.id, "closing");
ifolder.close();
} catch (MessagingException ex) {
Log.w(ex);
} finally {
Log.i(folder.name + " closed");
db.folder().setFolderState(folder.id, null);
db.folder().setFolderSyncState(folder.id, null);
}
}
}
private void onFolderSync(long aid) {
DB db = DB.getInstance(this);
EntityAccount account = db.account().getAccount(aid);
@ -402,17 +323,6 @@ public class ServiceUI extends IntentService {
}
}
public static void process(Context context, long folder) {
try {
context.startService(
new Intent(context, ServiceUI.class)
.setAction("process:" + folder));
} catch (IllegalStateException ex) {
Log.w(ex);
// The background service will handle the operation
}
}
public static void fsync(Context context, long account) {
try {
context.startService(

@ -0,0 +1,150 @@
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.MessagingException;
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.OneTimeWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
public class WorkerForeground extends Worker {
public WorkerForeground(@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 (MessagingException 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();
}
@Override
public void onStopped() {
Log.i("Worked stopped");
}
static void queue(long fid) {
String tag = "folder:" + fid;
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("folder", fid).build();
OneTimeWorkRequest workRequest =
new OneTimeWorkRequest.Builder(WorkerForeground.class)
.addTag(tag)
.setInputData(data)
.build();
WorkManager.getInstance().enqueue(workRequest);
Log.i("Queued work " + tag);
}
}
Loading…
Cancel
Save