|
@ -96,7 +96,6 @@ import androidx.lifecycle.Observer; |
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager; |
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager; |
|
|
|
|
|
|
|
|
public class ServiceSynchronize extends LifecycleService { |
|
|
public class ServiceSynchronize extends LifecycleService { |
|
|
private ServiceState state = new ServiceState(); |
|
|
|
|
|
private ExecutorService executor = Executors.newSingleThreadExecutor(); |
|
|
private ExecutorService executor = Executors.newSingleThreadExecutor(); |
|
|
|
|
|
|
|
|
private static final int NOTIFICATION_SYNCHRONIZE = 1; |
|
|
private static final int NOTIFICATION_SYNCHRONIZE = 1; |
|
@ -109,11 +108,6 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
static final String ACTION_PROCESS_FOLDER = BuildConfig.APPLICATION_ID + ".PROCESS_FOLDER"; |
|
|
static final String ACTION_PROCESS_FOLDER = BuildConfig.APPLICATION_ID + ".PROCESS_FOLDER"; |
|
|
static final String ACTION_PROCESS_OUTBOX = BuildConfig.APPLICATION_ID + ".PROCESS_OUTBOX"; |
|
|
static final String ACTION_PROCESS_OUTBOX = BuildConfig.APPLICATION_ID + ".PROCESS_OUTBOX"; |
|
|
|
|
|
|
|
|
private class ServiceState { |
|
|
|
|
|
boolean running = false; |
|
|
|
|
|
List<Thread> threads = new ArrayList<>(); // accounts |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public ServiceSynchronize() { |
|
|
public ServiceSynchronize() { |
|
|
// https://docs.oracle.com/javaee/6/api/javax/mail/internet/package-summary.html |
|
|
// https://docs.oracle.com/javaee/6/api/javax/mail/internet/package-summary.html |
|
|
System.setProperty("mail.mime.ignoreunknownencoding", "true"); |
|
|
System.setProperty("mail.mime.ignoreunknownencoding", "true"); |
|
@ -301,7 +295,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void monitorAccount(final EntityAccount account) { |
|
|
|
|
|
|
|
|
private void monitorAccount(final EntityAccount account, final ServiceState state) { |
|
|
Log.i(Helper.TAG, account.name + " start "); |
|
|
Log.i(Helper.TAG, account.name + " start "); |
|
|
|
|
|
|
|
|
while (state.running) { |
|
|
while (state.running) { |
|
@ -377,7 +371,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
mapFolder.put(folder.id, ifolder); |
|
|
mapFolder.put(folder.id, ifolder); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
monitorFolder(account, folder, fstore, ifolder); |
|
|
|
|
|
|
|
|
monitorFolder(account, folder, fstore, ifolder, state); |
|
|
} catch (FolderNotFoundException ex) { |
|
|
} catch (FolderNotFoundException ex) { |
|
|
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); |
|
|
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); |
|
|
} catch (Throwable ex) { |
|
|
} catch (Throwable ex) { |
|
@ -567,7 +561,10 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
Log.i(Helper.TAG, account.name + " stopped"); |
|
|
Log.i(Helper.TAG, account.name + " stopped"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void monitorFolder(final EntityAccount account, final EntityFolder folder, final IMAPStore istore, final IMAPFolder ifolder) throws MessagingException, JSONException, IOException { |
|
|
|
|
|
|
|
|
private void monitorFolder( |
|
|
|
|
|
final EntityAccount account, final EntityFolder folder, |
|
|
|
|
|
final IMAPStore istore, final IMAPFolder ifolder, |
|
|
|
|
|
ServiceState state) throws MessagingException, JSONException, IOException { |
|
|
// Listen for new and deleted messages |
|
|
// Listen for new and deleted messages |
|
|
ifolder.addMessageCountListener(new MessageCountAdapter() { |
|
|
ifolder.addMessageCountListener(new MessageCountAdapter() { |
|
|
@Override |
|
|
@Override |
|
@ -1245,7 +1242,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { |
|
|
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { |
|
|
private Thread mainThread; |
|
|
|
|
|
|
|
|
final ServiceState state = new ServiceState(); |
|
|
private EntityFolder outbox = null; |
|
|
private EntityFolder outbox = null; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@ -1253,54 +1250,48 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
Log.i(Helper.TAG, "Available " + network); |
|
|
Log.i(Helper.TAG, "Available " + network); |
|
|
|
|
|
|
|
|
synchronized (state) { |
|
|
synchronized (state) { |
|
|
if (!state.running) { |
|
|
|
|
|
state.threads.clear(); |
|
|
|
|
|
state.running = true; |
|
|
|
|
|
|
|
|
state.running = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
mainThread = new Thread(new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
DB db = DB.getInstance(ServiceSynchronize.this); |
|
|
|
|
|
try { |
|
|
|
|
|
List<EntityAccount> accounts = db.account().getAccounts(true); |
|
|
|
|
|
if (accounts.size() == 0) { |
|
|
|
|
|
Log.i(Helper.TAG, "No accounts, halt"); |
|
|
|
|
|
stopSelf(); |
|
|
|
|
|
} else |
|
|
|
|
|
for (final EntityAccount account : accounts) { |
|
|
|
|
|
Log.i(Helper.TAG, account.host + "/" + account.user + " run"); |
|
|
|
|
|
Thread thread = new Thread(new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
try { |
|
|
|
|
|
monitorAccount(account); |
|
|
|
|
|
} catch (Throwable ex) { |
|
|
|
|
|
// Fallsafe |
|
|
|
|
|
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, "sync.account." + account.id); |
|
|
|
|
|
state.threads.add(thread); |
|
|
|
|
|
thread.start(); |
|
|
|
|
|
|
|
|
new Thread(new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
DB db = DB.getInstance(ServiceSynchronize.this); |
|
|
|
|
|
try { |
|
|
|
|
|
List<EntityAccount> accounts = db.account().getAccounts(true); |
|
|
|
|
|
if (accounts.size() == 0) { |
|
|
|
|
|
Log.i(Helper.TAG, "No accounts, halt"); |
|
|
|
|
|
stopSelf(); |
|
|
|
|
|
} else |
|
|
|
|
|
for (final EntityAccount account : accounts) { |
|
|
|
|
|
Log.i(Helper.TAG, account.host + "/" + account.user + " run"); |
|
|
|
|
|
new Thread(new Runnable() { |
|
|
|
|
|
@Override |
|
|
|
|
|
public void run() { |
|
|
|
|
|
try { |
|
|
|
|
|
monitorAccount(account, state); |
|
|
|
|
|
} catch (Throwable ex) { |
|
|
|
|
|
// Fallsafe |
|
|
|
|
|
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} catch (Throwable ex) { |
|
|
|
|
|
// Failsafe |
|
|
|
|
|
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); |
|
|
|
|
|
|
|
|
}, "sync.account." + account.id).start(); |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (Throwable ex) { |
|
|
|
|
|
// Failsafe |
|
|
|
|
|
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
outbox = db.folder().getOutbox(); |
|
|
|
|
|
if (outbox != null) { |
|
|
|
|
|
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this); |
|
|
|
|
|
lbm.registerReceiver(receiverOutbox, new IntentFilter(ACTION_PROCESS_OUTBOX)); |
|
|
|
|
|
Log.i(Helper.TAG, outbox.name + " listen operations"); |
|
|
|
|
|
lbm.sendBroadcast(new Intent(ACTION_PROCESS_OUTBOX)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
outbox = db.folder().getOutbox(); |
|
|
|
|
|
if (outbox != null) { |
|
|
|
|
|
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this); |
|
|
|
|
|
lbm.registerReceiver(receiverOutbox, new IntentFilter(ACTION_PROCESS_OUTBOX)); |
|
|
|
|
|
Log.i(Helper.TAG, outbox.name + " listen operations"); |
|
|
|
|
|
lbm.sendBroadcast(new Intent(ACTION_PROCESS_OUTBOX)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
}, "sync.main"); |
|
|
|
|
|
mainThread.start(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
}, "sync.main").start(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@ -1308,10 +1299,8 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
Log.i(Helper.TAG, "Lost " + network); |
|
|
Log.i(Helper.TAG, "Lost " + network); |
|
|
|
|
|
|
|
|
synchronized (state) { |
|
|
synchronized (state) { |
|
|
if (state.running) { |
|
|
|
|
|
state.running = false; |
|
|
|
|
|
state.notifyAll(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
state.running = false; |
|
|
|
|
|
state.notifyAll(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (outbox != null) { |
|
|
if (outbox != null) { |
|
@ -1330,9 +1319,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
public void run() { |
|
|
public void run() { |
|
|
try { |
|
|
try { |
|
|
Log.i(Helper.TAG, outbox.name + " start operations"); |
|
|
Log.i(Helper.TAG, outbox.name + " start operations"); |
|
|
synchronized (outbox) { |
|
|
|
|
|
processOperations(outbox, null, null); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
processOperations(outbox, null, null); |
|
|
} catch (Throwable ex) { |
|
|
} catch (Throwable ex) { |
|
|
Log.e(Helper.TAG, outbox.name + " " + ex + "\n" + Log.getStackTraceString(ex)); |
|
|
Log.e(Helper.TAG, outbox.name + " " + ex + "\n" + Log.getStackTraceString(ex)); |
|
|
reportError(null, outbox.name, ex); |
|
|
reportError(null, outbox.name, ex); |
|
@ -1382,4 +1369,8 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
context.stopService(new Intent(context, ServiceSynchronize.class)); |
|
|
context.stopService(new Intent(context, ServiceSynchronize.class)); |
|
|
start(context); |
|
|
start(context); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private class ServiceState { |
|
|
|
|
|
boolean running = false; |
|
|
|
|
|
} |
|
|
} |
|
|
} |