|
@ -29,10 +29,12 @@ import android.content.BroadcastReceiver; |
|
|
import android.content.Context; |
|
|
import android.content.Context; |
|
|
import android.content.Intent; |
|
|
import android.content.Intent; |
|
|
import android.content.IntentFilter; |
|
|
import android.content.IntentFilter; |
|
|
|
|
|
import android.media.RingtoneManager; |
|
|
import android.net.ConnectivityManager; |
|
|
import android.net.ConnectivityManager; |
|
|
import android.net.Network; |
|
|
import android.net.Network; |
|
|
import android.net.NetworkCapabilities; |
|
|
import android.net.NetworkCapabilities; |
|
|
import android.net.NetworkRequest; |
|
|
import android.net.NetworkRequest; |
|
|
|
|
|
import android.net.Uri; |
|
|
import android.os.Build; |
|
|
import android.os.Build; |
|
|
import android.os.SystemClock; |
|
|
import android.os.SystemClock; |
|
|
import android.support.annotation.Nullable; |
|
|
import android.support.annotation.Nullable; |
|
@ -95,6 +97,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
private ExecutorService executor = Executors.newSingleThreadExecutor(); |
|
|
private ExecutorService executor = Executors.newSingleThreadExecutor(); |
|
|
|
|
|
|
|
|
private static final int NOTIFICATION_SYNCHRONIZE = 1; |
|
|
private static final int NOTIFICATION_SYNCHRONIZE = 1; |
|
|
|
|
|
private static final int NOTIFICATION_UNSEEN = 2; |
|
|
|
|
|
|
|
|
private static final long NOOP_INTERVAL = 9 * 60 * 1000L; // ms |
|
|
private static final long NOOP_INTERVAL = 9 * 60 * 1000L; // ms |
|
|
private static final int FETCH_BATCH_SIZE = 10; |
|
|
private static final int FETCH_BATCH_SIZE = 10; |
|
@ -120,7 +123,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
public void onCreate() { |
|
|
public void onCreate() { |
|
|
Log.i(Helper.TAG, "Service create"); |
|
|
Log.i(Helper.TAG, "Service create"); |
|
|
super.onCreate(); |
|
|
super.onCreate(); |
|
|
startForeground(NOTIFICATION_SYNCHRONIZE, getNotification(0, -1, 0).build()); |
|
|
|
|
|
|
|
|
startForeground(NOTIFICATION_SYNCHRONIZE, getNotification(0, 0).build()); |
|
|
|
|
|
|
|
|
// Listen for network changes |
|
|
// Listen for network changes |
|
|
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
|
|
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
|
@ -130,11 +133,25 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
cm.registerNetworkCallback(builder.build(), networkCallback); |
|
|
cm.registerNetworkCallback(builder.build(), networkCallback); |
|
|
|
|
|
|
|
|
DB.getInstance(this).account().liveStats().observe(this, new Observer<TupleAccountStats>() { |
|
|
DB.getInstance(this).account().liveStats().observe(this, new Observer<TupleAccountStats>() { |
|
|
|
|
|
private int prev_unseen = -1; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void onChanged(@Nullable TupleAccountStats stats) { |
|
|
public void onChanged(@Nullable TupleAccountStats stats) { |
|
|
if (stats != null) { |
|
|
if (stats != null) { |
|
|
NotificationManager nm = getSystemService(NotificationManager.class); |
|
|
NotificationManager nm = getSystemService(NotificationManager.class); |
|
|
nm.notify(NOTIFICATION_SYNCHRONIZE, getNotification(stats.accounts, stats.operations, stats.unseen).build()); |
|
|
|
|
|
|
|
|
nm.notify(NOTIFICATION_SYNCHRONIZE, |
|
|
|
|
|
getNotification(stats.accounts, stats.operations).build()); |
|
|
|
|
|
|
|
|
|
|
|
if (stats.unseen > 0) { |
|
|
|
|
|
if (stats.unseen != prev_unseen) { |
|
|
|
|
|
boolean sound = (stats.unseen > prev_unseen); |
|
|
|
|
|
nm.cancel(NOTIFICATION_UNSEEN); |
|
|
|
|
|
nm.notify(NOTIFICATION_UNSEEN, getNotification(stats.unseen, sound).build()); |
|
|
|
|
|
} |
|
|
|
|
|
} else |
|
|
|
|
|
nm.cancel(NOTIFICATION_UNSEEN); |
|
|
|
|
|
|
|
|
|
|
|
prev_unseen = stats.unseen; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
@ -165,7 +182,7 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
return START_STICKY; |
|
|
return START_STICKY; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private Notification.Builder getNotification(int accounts, int operations, int unseen) { |
|
|
|
|
|
|
|
|
private Notification.Builder getNotification(int accounts, int operations) { |
|
|
// Build pending intent |
|
|
// Build pending intent |
|
|
Intent intent = new Intent(this, ActivityView.class); |
|
|
Intent intent = new Intent(this, ActivityView.class); |
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
|
@ -175,25 +192,57 @@ public class ServiceSynchronize extends LifecycleService { |
|
|
// Build notification |
|
|
// Build notification |
|
|
Notification.Builder builder; |
|
|
Notification.Builder builder; |
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) |
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) |
|
|
builder = new Notification.Builder(this, unseen == 0 ? "service" : "notification"); |
|
|
|
|
|
|
|
|
builder = new Notification.Builder(this, "service"); |
|
|
else |
|
|
else |
|
|
builder = new Notification.Builder(this); |
|
|
builder = new Notification.Builder(this); |
|
|
|
|
|
|
|
|
builder |
|
|
builder |
|
|
.setSmallIcon(R.drawable.baseline_mail_outline_24) |
|
|
.setSmallIcon(R.drawable.baseline_mail_outline_24) |
|
|
.setContentTitle(getString(R.string.title_notification_synchronizing, accounts)) |
|
|
.setContentTitle(getString(R.string.title_notification_synchronizing, accounts)) |
|
|
.setContentText(getString(R.string.title_notification_unseen, unseen)) |
|
|
|
|
|
|
|
|
.setContentText(getString(R.string.title_notification_operations, operations)) |
|
|
.setContentIntent(pi) |
|
|
.setContentIntent(pi) |
|
|
.setStyle(new Notification.BigTextStyle().setSummaryText(getString(R.string.title_operations, operations))) |
|
|
|
|
|
.setAutoCancel(false) |
|
|
.setAutoCancel(false) |
|
|
.setShowWhen(unseen > 0) |
|
|
|
|
|
.setPriority(unseen == 0 ? Notification.PRIORITY_MIN : Notification.PRIORITY_DEFAULT) |
|
|
|
|
|
|
|
|
.setShowWhen(false) |
|
|
|
|
|
.setPriority(Notification.PRIORITY_MIN) |
|
|
.setCategory(Notification.CATEGORY_STATUS) |
|
|
.setCategory(Notification.CATEGORY_STATUS) |
|
|
.setVisibility(Notification.VISIBILITY_SECRET); |
|
|
.setVisibility(Notification.VISIBILITY_SECRET); |
|
|
|
|
|
|
|
|
return builder; |
|
|
return builder; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Notification.Builder getNotification(int unseen, boolean sound) { |
|
|
|
|
|
// Build pending intent |
|
|
|
|
|
Intent intent = new Intent(this, ActivityView.class); |
|
|
|
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
|
|
|
|
|
PendingIntent pi = PendingIntent.getActivity( |
|
|
|
|
|
this, ActivityView.REQUEST_VIEW, intent, PendingIntent.FLAG_UPDATE_CURRENT); |
|
|
|
|
|
|
|
|
|
|
|
// Build notification |
|
|
|
|
|
Notification.Builder builder; |
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) |
|
|
|
|
|
builder = new Notification.Builder(this, "notification"); |
|
|
|
|
|
else |
|
|
|
|
|
builder = new Notification.Builder(this); |
|
|
|
|
|
|
|
|
|
|
|
builder |
|
|
|
|
|
.setSmallIcon(R.drawable.baseline_mail_24) |
|
|
|
|
|
.setContentTitle(getString(R.string.title_notification_unseen, unseen)) |
|
|
|
|
|
.setContentIntent(pi) |
|
|
|
|
|
.setAutoCancel(true) |
|
|
|
|
|
.setShowWhen(false) // when of first or last new email? |
|
|
|
|
|
.setPriority(Notification.PRIORITY_DEFAULT) |
|
|
|
|
|
.setCategory(Notification.CATEGORY_STATUS) |
|
|
|
|
|
.setVisibility(Notification.VISIBILITY_PUBLIC); |
|
|
|
|
|
|
|
|
|
|
|
if (sound) { |
|
|
|
|
|
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); |
|
|
|
|
|
builder.setSound(uri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return builder; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Notification.Builder getNotification(String action, Throwable ex) { |
|
|
private Notification.Builder getNotification(String action, Throwable ex) { |
|
|
// Build pending intent |
|
|
// Build pending intent |
|
|
Intent intent = new Intent(this, ActivityView.class); |
|
|
Intent intent = new Intent(this, ActivityView.class); |
|
|