Keep network state

pull/153/head
M66B 7 years ago
parent fa579d3c10
commit 4ca5cd0540

@ -315,7 +315,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
protected Void onExecute(Context context, Bundle args) {
long fid = args.getLong("folder");
if (!Helper.suitableNetwork(context, false))
if (!Helper.getNetworkState(context).isSuitable())
throw new IllegalArgumentException(context.getString(R.string.title_no_internet));
DB db = DB.getInstance(context);

@ -144,7 +144,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
private boolean subject_italic;
private int zoom;
private String sort;
private boolean internet;
private boolean suitable;
private IProperties properties;
private boolean date;
@ -778,8 +778,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
grpHeaders.setVisibility(show_headers ? View.VISIBLE : View.GONE);
if (show_headers && message.headers == null) {
pbHeaders.setVisibility(internet ? View.VISIBLE : View.GONE);
tvNoInternetHeaders.setVisibility(internet ? View.GONE : View.VISIBLE);
pbHeaders.setVisibility(suitable ? View.VISIBLE : View.GONE);
tvNoInternetHeaders.setVisibility(suitable ? View.GONE : View.VISIBLE);
} else {
pbHeaders.setVisibility(View.GONE);
tvNoInternetHeaders.setVisibility(View.GONE);
@ -967,8 +967,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
}.execute(context, owner, sargs, "message:actions");
// Message text
pbBody.setVisibility(internet || message.content ? View.VISIBLE : View.GONE);
tvNoInternetBody.setVisibility(internet || message.content ? View.GONE : View.VISIBLE);
pbBody.setVisibility(suitable || message.content ? View.VISIBLE : View.GONE);
tvNoInternetBody.setVisibility(suitable || message.content ? View.GONE : View.VISIBLE);
if (message.content)
if (show_html)
@ -1016,9 +1016,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
cbInline.setOnCheckedChangeListener(null);
cbInline.setChecked(show_inline);
cbInline.setVisibility(has_inline ? View.VISIBLE : View.GONE);
btnDownloadAttachments.setVisibility(download && internet ? View.VISIBLE : View.GONE);
btnDownloadAttachments.setVisibility(download && suitable ? View.VISIBLE : View.GONE);
btnSaveAttachments.setVisibility(save ? View.VISIBLE : View.GONE);
tvNoInternetAttachments.setVisibility(downloading && !internet ? View.VISIBLE : View.GONE);
tvNoInternetAttachments.setVisibility(downloading && !suitable ? View.VISIBLE : View.GONE);
cbInline.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
@ -2398,7 +2398,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
properties.setValue("headers", data.message.id, show_headers);
if (show_headers && data.message.headers == null) {
grpHeaders.setVisibility(View.VISIBLE);
if (internet)
if (suitable)
pbHeaders.setVisibility(View.VISIBLE);
else
tvNoInternetHeaders.setVisibility(View.VISIBLE);
@ -2939,7 +2939,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
this.subject_italic = prefs.getBoolean("subject_italic", true);
this.zoom = zoom;
this.sort = sort;
this.internet = Helper.suitableNetwork(context, false);
this.suitable = Helper.getNetworkState(context).isSuitable();
this.properties = properties;
@ -3021,9 +3021,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
}
void checkInternet() {
boolean internet = Helper.suitableNetwork(context, false);
if (this.internet != internet) {
this.internet = internet;
boolean suitable = Helper.getNetworkState(context).isSuitable();
if (this.suitable != suitable) {
this.suitable = suitable;
notifyDataSetChanged();
}
}

@ -1037,7 +1037,7 @@ class Core {
downloadMessage(
context,
folder, ifolder,
(IMAPMessage) isub[j], ids[from + j]);
(IMAPMessage) isub[j], ids[from + j], state);
} catch (FolderClosedException ex) {
throw ex;
} catch (FolderClosedIOException ex) {
@ -1380,7 +1380,7 @@ class Core {
static void downloadMessage(
Context context,
EntityFolder folder, IMAPFolder ifolder,
IMAPMessage imessage, long id) throws MessagingException, IOException {
IMAPMessage imessage, long id, State state) throws MessagingException, IOException {
DB db = DB.getInstance(context);
EntityMessage message = db.message().getMessage(id);
if (message == null)
@ -1393,18 +1393,16 @@ class Core {
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
MessageHelper helper = new MessageHelper(imessage);
Boolean isMetered = Helper.isMetered(context, false);
boolean metered = (isMetered == null || isMetered);
boolean fetch = false;
if (!message.content)
if (!metered || (message.size != null && message.size < maxSize))
if (state.getNetworkState().isUnmetered() || (message.size != null && message.size < maxSize))
fetch = true;
if (!fetch)
for (EntityAttachment attachment : attachments)
if (!attachment.available)
if (!metered || (attachment.size != null && attachment.size < maxSize)) {
if (state.getNetworkState().isUnmetered() || (attachment.size != null && attachment.size < maxSize)) {
fetch = true;
break;
}
@ -1425,7 +1423,7 @@ class Core {
MessageHelper.MessageParts parts = helper.getMessageParts();
if (!message.content) {
if (!metered || (message.size != null && message.size < maxSize)) {
if (state.getNetworkState().isUnmetered() || (message.size != null && message.size < maxSize)) {
String body = parts.getHtml(context);
Helper.writeText(message.getFile(context), body);
db.message().setMessageContent(message.id, true,
@ -1436,7 +1434,7 @@ class Core {
for (EntityAttachment attachment : attachments)
if (!attachment.available)
if (!metered || (attachment.size != null && attachment.size < maxSize))
if (state.getNetworkState().isUnmetered() || (attachment.size != null && attachment.size < maxSize))
try {
parts.downloadAttachment(context, attachment.sequence - 1, attachment.id);
} catch (Throwable ex) {
@ -1854,10 +1852,23 @@ class Core {
}
static class State {
private Helper.NetworkState networkState;
private Thread thread;
private Semaphore semaphore = new Semaphore(0);
private boolean running = true;
State(Helper.NetworkState networkState) {
this.networkState = networkState;
}
State(State parent) {
this(parent.networkState);
}
Helper.NetworkState getNetworkState() {
return networkState;
}
void runnable(Runnable runnable, String name) {
thread = new Thread(runnable, name);
thread.setPriority(THREAD_PRIORITY_BACKGROUND);

@ -714,13 +714,13 @@ public class FragmentCompose extends FragmentBase {
};
private void checkInternet() {
boolean internet = Helper.suitableNetwork(getContext(), false);
boolean suitable = Helper.getNetworkState(getContext()).isSuitable();
Boolean content = (Boolean) tvNoInternet.getTag();
tvNoInternet.setVisibility(!internet && content != null && !content ? View.VISIBLE : View.GONE);
tvNoInternet.setVisibility(!suitable && content != null && !content ? View.VISIBLE : View.GONE);
Boolean downloading = (Boolean) rvAttachment.getTag();
tvNoInternetAttachments.setVisibility(!internet && downloading != null && downloading ? View.VISIBLE : View.GONE);
tvNoInternetAttachments.setVisibility(!suitable && downloading != null && downloading ? View.VISIBLE : View.GONE);
}
@Override

@ -288,7 +288,7 @@ public class FragmentFolders extends FragmentBase {
protected Void onExecute(Context context, Bundle args) {
long aid = args.getLong("account");
if (!Helper.suitableNetwork(context, false))
if (!Helper.getNetworkState(context).isSuitable())
throw new IllegalArgumentException(context.getString(R.string.title_no_internet));
DB db = DB.getInstance(context);

@ -515,7 +515,7 @@ public class FragmentMessages extends FragmentBase {
protected Void onExecute(Context context, Bundle args) {
long fid = args.getLong("folder");
if (!Helper.suitableNetwork(context, false))
if (!Helper.getNetworkState(context).isSuitable())
throw new IllegalArgumentException(context.getString(R.string.title_no_internet));
@ -2096,8 +2096,7 @@ public class FragmentMessages extends FragmentBase {
if (download == 0)
download = Long.MAX_VALUE;
Boolean isMetered = Helper.isMetered(getContext(), false);
boolean metered = (isMetered == null || isMetered);
boolean unmetered = Helper.getNetworkState(getContext()).isUnmetered();
int count = 0;
int unseen = 0;
@ -2139,7 +2138,7 @@ public class FragmentMessages extends FragmentBase {
expand = messages.get(0);
if (expand != null &&
(expand.content || !metered || (expand.size != null && expand.size < download))) {
(expand.content || unmetered || (expand.size != null && expand.size < download))) {
if (!values.containsKey("expanded"))
values.put("expanded", new ArrayList<Long>());
values.get("expanded").add(expand.id);

@ -687,11 +687,10 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
@Override
public void run() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
Boolean metered = Helper.isMetered(getContext(), false);
Helper.NetworkState networkState = Helper.getNetworkState(getContext());
tvConnectionType.setVisibility(metered == null ? View.GONE : View.VISIBLE);
if (metered != null)
tvConnectionType.setText(metered ? R.string.title_legend_metered : R.string.title_legend_unmetered);
tvConnectionType.setText(networkState.isUnmetered() ? R.string.title_legend_unmetered : R.string.title_legend_metered);
tvConnectionType.setVisibility(networkState.isConnected() ? View.VISIBLE : View.GONE);
}
}
});

@ -700,17 +700,42 @@ public class Helper {
return filename.substring(index + 1);
}
static boolean suitableNetwork(Context context, boolean log) {
static class NetworkState {
private Boolean connected = null;
private Boolean suitable = null;
private Boolean unmetered = null;
boolean isConnected() {
return (connected != null && connected);
}
boolean isSuitable() {
return (suitable != null && suitable);
}
boolean isUnmetered() {
return (unmetered != null && unmetered);
}
public void update(NetworkState newState) {
suitable = newState.suitable;
unmetered = newState.unmetered;
}
}
static NetworkState getNetworkState(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean metered = prefs.getBoolean("metered", true);
Boolean isMetered = isMetered(context, log);
boolean suitable = (isMetered != null && (metered || !isMetered));
if (log)
EntityLog.log(context, "suitable=" + suitable + " metered=" + metered + " isMetered=" + isMetered);
return suitable;
NetworkState state = new NetworkState();
Boolean isMetered = isMetered(context, false);
state.connected = (isMetered != null);
state.unmetered = (isMetered != null && !isMetered);
state.suitable = (isMetered != null && (metered || !isMetered));
return state;
}
static Boolean isMetered(Context context, boolean log) {
private static Boolean isMetered(Context context, boolean log) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {

@ -147,7 +147,7 @@ public class ServiceSend extends LifecycleService {
}
private void check() {
if (!Helper.suitableNetwork(ServiceSend.this, false))
if (!Helper.getNetworkState(ServiceSend.this).isSuitable())
return;
if (thread != null && thread.isAlive())
@ -215,7 +215,7 @@ public class ServiceSend extends LifecycleService {
Log.i(outbox.name + " end op=" + op.id + "/" + op.name);
}
if (!Helper.suitableNetwork(ServiceSend.this, false))
if (!Helper.getNetworkState(ServiceSend.this).isSuitable())
break;
}

@ -83,6 +83,7 @@ import androidx.preference.PreferenceManager;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
public class ServiceSynchronize extends LifecycleService {
private Helper.NetworkState networkState = new Helper.NetworkState();
private Core.State state;
private boolean started = false;
private int queued = 0;
@ -284,7 +285,7 @@ public class ServiceSynchronize extends LifecycleService {
private void queue_reload(final boolean start, final String reason) {
final boolean doStop = started;
final boolean doStart = (start && isEnabled() && Helper.suitableNetwork(this, true));
final boolean doStart = (start && isEnabled() && networkState.isSuitable());
EntityLog.log(this, "Queue reload" +
" doStop=" + doStop + " doStart=" + doStart + " queued=" + queued + " " + reason);
@ -355,7 +356,7 @@ public class ServiceSynchronize extends LifecycleService {
private void start() {
EntityLog.log(this, "Main start");
state = new Core.State();
state = new Core.State(networkState);
state.runnable(new Runnable() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
@ -390,7 +391,7 @@ public class ServiceSynchronize extends LifecycleService {
account.deleteNotificationChannel(ServiceSynchronize.this);
Log.i(account.host + "/" + account.user + " run");
final Core.State astate = new Core.State();
final Core.State astate = new Core.State(state);
astate.runnable(new Runnable() {
@Override
public void run() {
@ -678,7 +679,7 @@ public class ServiceSynchronize extends LifecycleService {
if (db.folder().getFolderDownload(folder.id))
Core.downloadMessage(ServiceSynchronize.this,
folder, (IMAPFolder) ifolder,
(IMAPMessage) imessage, message.id);
(IMAPMessage) imessage, message.id, state);
} catch (MessageRemovedException ex) {
Log.w(folder.name, ex);
} catch (FolderClosedException ex) {
@ -767,7 +768,7 @@ public class ServiceSynchronize extends LifecycleService {
if (db.folder().getFolderDownload(folder.id))
Core.downloadMessage(ServiceSynchronize.this,
folder, (IMAPFolder) ifolder,
(IMAPMessage) e.getMessage(), message.id);
(IMAPMessage) e.getMessage(), message.id, state);
} catch (MessageRemovedException ex) {
Log.w(folder.name, ex);
} catch (FolderClosedException ex) {
@ -1087,12 +1088,14 @@ public class ServiceSynchronize extends LifecycleService {
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
networkState.update(Helper.getNetworkState(ServiceSynchronize.this));
synchronized (ServiceSynchronize.this) {
try {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
EntityLog.log(ServiceSynchronize.this, "Available " + network + " " + cm.getNetworkInfo(network));
if (!started && Helper.suitableNetwork(ServiceSynchronize.this, true))
if (!started && networkState.isSuitable())
queue_reload(true, "connect " + network);
} catch (Throwable ex) {
Log.e(ex);
@ -1102,11 +1105,13 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
networkState.update(Helper.getNetworkState(ServiceSynchronize.this));
synchronized (ServiceSynchronize.this) {
try {
if (!started) {
EntityLog.log(ServiceSynchronize.this, "Network " + network + " capabilities " + capabilities);
if (Helper.suitableNetwork(ServiceSynchronize.this, true))
if (networkState.isSuitable())
queue_reload(true, "capabilities " + network);
}
} catch (Throwable ex) {
@ -1117,11 +1122,13 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onLost(Network network) {
networkState.update(Helper.getNetworkState(ServiceSynchronize.this));
synchronized (ServiceSynchronize.this) {
try {
EntityLog.log(ServiceSynchronize.this, "Lost " + network);
if (started && !Helper.suitableNetwork(ServiceSynchronize.this, true)) {
if (started && !networkState.isSuitable()) {
lastLost = new Date().getTime();
queue_reload(false, "disconnect " + network);
}

@ -157,7 +157,7 @@ public class ViewModelBrowse extends ViewModel {
try {
// Check connectivity
if (!Helper.suitableNetwork(state.context, false))
if (!Helper.getNetworkState(state.context).isSuitable())
throw new IllegalArgumentException(state.context.getString(R.string.title_no_internet));
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(state.context);

Loading…
Cancel
Save