diff --git a/app/src/main/java/org/fdroid/fdroid/Preferences.java b/app/src/main/java/org/fdroid/fdroid/Preferences.java index 7a5b91bed..cfe402d47 100644 --- a/app/src/main/java/org/fdroid/fdroid/Preferences.java +++ b/app/src/main/java/org/fdroid/fdroid/Preferences.java @@ -231,7 +231,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh return preferences.getBoolean(PREF_AUTO_DOWNLOAD_INSTALL_UPDATES, false); } - public boolean isUpdateOnlyOnWifi() { + public boolean isUpdateOnlyOnUnmeteredNetworks() { return preferences.getBoolean(PREF_UPD_WIFI_ONLY, false); } diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index ff8c810f9..6586bae3f 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -31,6 +31,8 @@ import android.database.Cursor; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.os.SystemClock; import android.preference.PreferenceManager; @@ -79,6 +81,12 @@ public class UpdateService extends IntentService { private static final int NOTIFY_ID_UPDATING = 0; private static final int NOTIFY_ID_UPDATES_AVAILABLE = 1; + private static final int FLAG_NET_UNAVAILABLE = 0; + private static final int FLAG_NET_METERED = 1; + private static final int FLAG_NET_NO_LIMIT = 2; + + private static Handler toastHandler; + private NotificationManager notificationManager; private NotificationCompat.Builder notificationBuilder; @@ -279,31 +287,52 @@ public class UpdateService extends IntentService { return false; } - return isNetworkAvailableForUpdate(this); + return true; } /** - * If we are to update the repos only on wifi, make sure that connection is active + * Gets the state of internet availability, whether there is no connection at all, + * whether the connection has no usage limit (like most WiFi), or whether this is + * a metered connection like most cellular plans or hotspot WiFi connections. */ - private static boolean isNetworkAvailableForUpdate(Context context) { + private static int getNetworkState(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - // this could be cellular or wifi NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - if (activeNetwork == null) { - return false; + if (activeNetwork == null || !activeNetwork.isConnected()) { + return FLAG_NET_UNAVAILABLE; } int networkType = activeNetwork.getType(); switch (networkType) { case ConnectivityManager.TYPE_ETHERNET: case ConnectivityManager.TYPE_WIFI: - return activeNetwork.isConnectedOrConnecting(); + if (Build.VERSION.SDK_INT >= 16 && cm.isActiveNetworkMetered()) { + return FLAG_NET_METERED; + } else { + return FLAG_NET_NO_LIMIT; + } default: - return Preferences.get().isUpdateOnlyOnWifi(); + return FLAG_NET_METERED; } } + /** + * In order to send a {@link Toast} from a {@link IntentService}, we have to do these tricks. + */ + private void sendNoInternetToast() { + if (toastHandler == null) { + toastHandler = new Handler(Looper.getMainLooper()); + } + toastHandler.post(new Runnable() { + @Override + public void run() { + Toast.makeText(getApplicationContext(), + R.string.warning_no_internet, Toast.LENGTH_SHORT).show(); + } + }); + } + @Override protected void onHandleIntent(Intent intent) { Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); @@ -318,9 +347,21 @@ public class UpdateService extends IntentService { try { // See if it's time to actually do anything yet... - if (manualUpdate) { - Utils.debugLog(TAG, "Unscheduled (manually requested) update"); - } else if (!verifyIsTimeForScheduledRun()) { + int netState = getNetworkState(this); + if (netState == FLAG_NET_UNAVAILABLE) { + Utils.debugLog(TAG, "No internet, cannot update"); + if (manualUpdate) { + sendNoInternetToast(); + } + return; + } + + if (manualUpdate || (netState == FLAG_NET_NO_LIMIT)) { + // triggered by the user, or by connecting to WiFi, etc. + Utils.debugLog(TAG, "manually requested update or on unlimited internet"); + } else if (Preferences.get().isUpdateOnlyOnUnmeteredNetworks() + || !verifyIsTimeForScheduledRun()) { + Utils.debugLog(TAG, "don't run update, we're on metered internet"); return; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d23295a97..fdb4542a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,7 +21,7 @@ Automatic update interval No automatic app list updates Only on Wi-Fi - Update app lists automatically only on Wi-Fi + Only update automatically on unmetered networks like Wi-Fi Automatically download updates Download the update files in the background Automatically install updates @@ -201,6 +201,7 @@ All repositories are up to date All other repos didn\'t create errors. Error during update: %s + Cannot update, are you connected to the internet? No permissions are used. Permissions You don\'t have any available app that can handle %s.