From e36d7719b3a5fce24a6b1ec4a4a10ccf10bd8565 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 14 Nov 2016 12:23:37 +0100 Subject: [PATCH] trigger an update after joining good wifi without JobSchedule Each time the device connects to a wifi network, this waits for 2 minutes, then if the wifi is still connected, it re-schedules the index update to happen now. The goal is to favor unmetered networks as much as possible when downloading the index and any automatic app updates. This is only needed on older platforms, JobScheduler handles this for us on android-21+ --- .../java/org/fdroid/fdroid/UpdateService.java | 47 +++++++++++++++++++ .../fdroid/net/WifiStateChangeService.java | 11 +++++ 2 files changed, 58 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 2a8ee528c..b30cbc13d 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Looper; @@ -51,6 +52,7 @@ import org.fdroid.fdroid.net.BluetoothDownloader; import org.fdroid.fdroid.net.ConnectivityMonitorService; import org.fdroid.fdroid.views.main.MainActivity; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -147,6 +149,51 @@ public class UpdateService extends IntentService { return updating; } + private static volatile boolean isScheduleIfStillOnWifiRunning; + + /** + * Waits for a period of time for the WiFi to settle, then if the WiFi is + * still active, it schedules an update. This is to encourage the use of + * unlimited networks over metered networks for index updates and auto + * downloads of app updates. Starting with {@code android-21}, this uses + * {@link android.app.job.JobScheduler} instead. + */ + public static void scheduleIfStillOnWifi(Context context) { + if (Build.VERSION.SDK_INT >= 21) { + throw new IllegalStateException("This should never be used on android-21 or newer!"); + } + if (isScheduleIfStillOnWifiRunning || !Preferences.get().isBackgroundDownloadAllowed()) { + return; + } + isScheduleIfStillOnWifiRunning = true; + new StillOnWifiAsyncTask(context).execute(); + } + + private static final class StillOnWifiAsyncTask extends AsyncTask { + + private final WeakReference contextWeakReference; + + private StillOnWifiAsyncTask(Context context) { + this.contextWeakReference = new WeakReference<>(context); + } + + @Override + protected Void doInBackground(Void... voids) { + Context context = contextWeakReference.get(); + try { + Thread.sleep(120000); + if (Preferences.get().isBackgroundDownloadAllowed()) { + Utils.debugLog(TAG, "scheduling update because there is good internet"); + schedule(context); + } + } catch (Exception e) { + Utils.debugLog(TAG, e.getMessage()); + } + isScheduleIfStillOnWifiRunning = false; + return null; + } + } + @Override public void onCreate() { super.onCreate(); diff --git a/app/src/main/java/org/fdroid/fdroid/net/WifiStateChangeService.java b/app/src/main/java/org/fdroid/fdroid/net/WifiStateChangeService.java index c4280c3cc..cdc99524f 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/WifiStateChangeService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/WifiStateChangeService.java @@ -8,6 +8,7 @@ import android.net.DhcpInfo; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.os.Build; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; @@ -15,6 +16,7 @@ import android.util.Log; import org.apache.commons.net.util.SubnetUtils; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; +import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.localrepo.LocalRepoKeyStore; @@ -42,6 +44,11 @@ import java.util.Locale; * changed. Having the {@code Thread} also makes it easy to kill work * that is in progress. *

+ * This also schedules an update to encourage updates happening on + * unmetered networks like typical WiFi rather than networks that can + * cost money or have caps. The logic for checking the state of the + * internet connection is in {@link org.fdroid.fdroid.UpdateService#onHandleIntent(Intent)} + *

* Some devices send multiple copies of given events, like a Moto G often * sends three {@code CONNECTED} events. So they have to be debounced to * keep the {@link #BROADCAST} useful. @@ -92,6 +99,10 @@ public class WifiStateChangeService extends IntentService { wifiInfoThread = new WifiInfoThread(); wifiInfoThread.start(); } + + if (Build.VERSION.SDK_INT < 21 && wifiState == WifiManager.WIFI_STATE_ENABLED) { + UpdateService.scheduleIfStillOnWifi(this); + } } }