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.