Merge branch 'fix-only-on-wifi' into 'master'
fix "Only on WiFi" to apply to all downloads See merge request fdroid/fdroidclient!669
This commit is contained in:
		
						commit
						3c14d273b2
					
				@ -270,7 +270,12 @@
 | 
				
			|||||||
        <service
 | 
					        <service
 | 
				
			||||||
                android:name=".DeleteCacheService"
 | 
					                android:name=".DeleteCacheService"
 | 
				
			||||||
                android:exported="false"/>
 | 
					                android:exported="false"/>
 | 
				
			||||||
        <service android:name=".net.WifiStateChangeService"/>
 | 
					        <service
 | 
				
			||||||
 | 
					                android:name=".net.WifiStateChangeService"
 | 
				
			||||||
 | 
					                android:exported="false"/>
 | 
				
			||||||
 | 
					        <service
 | 
				
			||||||
 | 
					                android:name=".net.ConnectivityMonitorService"
 | 
				
			||||||
 | 
					                android:exported="false"/>
 | 
				
			||||||
        <service android:name=".localrepo.SwapService"/>
 | 
					        <service android:name=".localrepo.SwapService"/>
 | 
				
			||||||
        <service
 | 
					        <service
 | 
				
			||||||
                android:name=".installer.InstallManagerService"
 | 
					                android:name=".installer.InstallManagerService"
 | 
				
			||||||
 | 
				
			|||||||
@ -64,6 +64,7 @@ import org.fdroid.fdroid.data.Repo;
 | 
				
			|||||||
import org.fdroid.fdroid.data.RepoProvider;
 | 
					import org.fdroid.fdroid.data.RepoProvider;
 | 
				
			||||||
import org.fdroid.fdroid.installer.ApkFileProvider;
 | 
					import org.fdroid.fdroid.installer.ApkFileProvider;
 | 
				
			||||||
import org.fdroid.fdroid.installer.InstallHistoryService;
 | 
					import org.fdroid.fdroid.installer.InstallHistoryService;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.net.ConnectivityMonitorService;
 | 
				
			||||||
import org.fdroid.fdroid.net.ImageLoaderForUIL;
 | 
					import org.fdroid.fdroid.net.ImageLoaderForUIL;
 | 
				
			||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
 | 
					import org.fdroid.fdroid.net.WifiStateChangeService;
 | 
				
			||||||
import org.fdroid.fdroid.views.hiding.HidingManager;
 | 
					import org.fdroid.fdroid.views.hiding.HidingManager;
 | 
				
			||||||
@ -110,6 +111,8 @@ public class FDroidApp extends Application {
 | 
				
			|||||||
    public static volatile String bssid;
 | 
					    public static volatile String bssid;
 | 
				
			||||||
    public static volatile Repo repo = new Repo();
 | 
					    public static volatile Repo repo = new Repo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static volatile int networkState = ConnectivityMonitorService.FLAG_NET_UNAVAILABLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static volatile String lastWorkingMirror = null;
 | 
					    private static volatile String lastWorkingMirror = null;
 | 
				
			||||||
    private static volatile int numTries = Integer.MAX_VALUE;
 | 
					    private static volatile int numTries = Integer.MAX_VALUE;
 | 
				
			||||||
    private static volatile int timeout = 10000;
 | 
					    private static volatile int timeout = 10000;
 | 
				
			||||||
@ -374,11 +377,10 @@ public class FDroidApp extends Application {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Context context = this;
 | 
					 | 
				
			||||||
        Preferences.get().registerUnstableUpdatesChangeListener(new Preferences.ChangeListener() {
 | 
					        Preferences.get().registerUnstableUpdatesChangeListener(new Preferences.ChangeListener() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void onPreferenceChange() {
 | 
					            public void onPreferenceChange() {
 | 
				
			||||||
                AppProvider.Helper.calcSuggestedApks(context);
 | 
					                AppProvider.Helper.calcSuggestedApks(FDroidApp.this);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -434,6 +436,8 @@ public class FDroidApp extends Application {
 | 
				
			|||||||
                .build();
 | 
					                .build();
 | 
				
			||||||
        ImageLoader.getInstance().init(config);
 | 
					        ImageLoader.getInstance().init(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ConnectivityMonitorService.registerAndStart(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FDroidApp.initWifiSettings();
 | 
					        FDroidApp.initWifiSettings();
 | 
				
			||||||
        WifiStateChangeService.start(this, null);
 | 
					        WifiStateChangeService.start(this, null);
 | 
				
			||||||
        // if the HTTPS pref changes, then update all affected things
 | 
					        // if the HTTPS pref changes, then update all affected things
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ import android.os.Build;
 | 
				
			|||||||
import android.preference.PreferenceManager;
 | 
					import android.preference.PreferenceManager;
 | 
				
			||||||
import android.util.Log;
 | 
					import android.util.Log;
 | 
				
			||||||
import info.guardianproject.netcipher.NetCipher;
 | 
					import info.guardianproject.netcipher.NetCipher;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.net.ConnectivityMonitorService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.net.InetSocketAddress;
 | 
					import java.net.InetSocketAddress;
 | 
				
			||||||
import java.net.Proxy;
 | 
					import java.net.Proxy;
 | 
				
			||||||
@ -273,8 +274,14 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
 | 
				
			|||||||
        return preferences.getBoolean(PREF_AUTO_DOWNLOAD_INSTALL_UPDATES, false);
 | 
					        return preferences.getBoolean(PREF_AUTO_DOWNLOAD_INSTALL_UPDATES, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean isUpdateOnlyOnUnmeteredNetworks() {
 | 
					    /**
 | 
				
			||||||
        return preferences.getBoolean(PREF_UPD_WIFI_ONLY, false);
 | 
					     * Do the network conditions and user preferences allow for things to be
 | 
				
			||||||
 | 
					     * downloaded in the background.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public boolean isBackgroundDownloadAllowed() {
 | 
				
			||||||
 | 
					        return FDroidApp.networkState == ConnectivityMonitorService.FLAG_NET_NO_LIMIT ||
 | 
				
			||||||
 | 
					                (FDroidApp.networkState == ConnectivityMonitorService.FLAG_NET_METERED
 | 
				
			||||||
 | 
					                        && !preferences.getBoolean(PREF_UPD_WIFI_ONLY, false));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -27,8 +27,6 @@ import android.content.Context;
 | 
				
			|||||||
import android.content.Intent;
 | 
					import android.content.Intent;
 | 
				
			||||||
import android.content.IntentFilter;
 | 
					import android.content.IntentFilter;
 | 
				
			||||||
import android.content.SharedPreferences;
 | 
					import android.content.SharedPreferences;
 | 
				
			||||||
import android.net.ConnectivityManager;
 | 
					 | 
				
			||||||
import android.net.NetworkInfo;
 | 
					 | 
				
			||||||
import android.os.Build;
 | 
					import android.os.Build;
 | 
				
			||||||
import android.os.Handler;
 | 
					import android.os.Handler;
 | 
				
			||||||
import android.os.Looper;
 | 
					import android.os.Looper;
 | 
				
			||||||
@ -49,6 +47,7 @@ import org.fdroid.fdroid.data.Repo;
 | 
				
			|||||||
import org.fdroid.fdroid.data.RepoProvider;
 | 
					import org.fdroid.fdroid.data.RepoProvider;
 | 
				
			||||||
import org.fdroid.fdroid.data.Schema;
 | 
					import org.fdroid.fdroid.data.Schema;
 | 
				
			||||||
import org.fdroid.fdroid.installer.InstallManagerService;
 | 
					import org.fdroid.fdroid.installer.InstallManagerService;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.net.ConnectivityMonitorService;
 | 
				
			||||||
import org.fdroid.fdroid.views.main.MainActivity;
 | 
					import org.fdroid.fdroid.views.main.MainActivity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
@ -79,10 +78,6 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private static final int NOTIFY_ID_UPDATING = 0;
 | 
					    private static final int NOTIFY_ID_UPDATING = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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 static Handler toastHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private NotificationManager notificationManager;
 | 
					    private NotificationManager notificationManager;
 | 
				
			||||||
@ -312,33 +307,6 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 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 int getNetworkState(Context context) {
 | 
					 | 
				
			||||||
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
 | 
					 | 
				
			||||||
        if (activeNetwork == null || !activeNetwork.isConnected()) {
 | 
					 | 
				
			||||||
            return FLAG_NET_UNAVAILABLE;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int networkType = activeNetwork.getType();
 | 
					 | 
				
			||||||
        switch (networkType) {
 | 
					 | 
				
			||||||
            case ConnectivityManager.TYPE_ETHERNET:
 | 
					 | 
				
			||||||
            case ConnectivityManager.TYPE_WIFI:
 | 
					 | 
				
			||||||
                if (Build.VERSION.SDK_INT >= 16 && cm.isActiveNetworkMetered()) {
 | 
					 | 
				
			||||||
                    return FLAG_NET_METERED;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return FLAG_NET_NO_LIMIT;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                return FLAG_NET_METERED;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * In order to send a {@link Toast} from a {@link IntentService}, we have to do these tricks.
 | 
					     * In order to send a {@link Toast} from a {@link IntentService}, we have to do these tricks.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -371,8 +339,8 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            // See if it's time to actually do anything yet...
 | 
					            // See if it's time to actually do anything yet...
 | 
				
			||||||
            int netState = getNetworkState(this);
 | 
					            int netState = ConnectivityMonitorService.getNetworkState(this);
 | 
				
			||||||
            if (netState == FLAG_NET_UNAVAILABLE) {
 | 
					            if (netState == ConnectivityMonitorService.FLAG_NET_UNAVAILABLE) {
 | 
				
			||||||
                Utils.debugLog(TAG, "No internet, cannot update");
 | 
					                Utils.debugLog(TAG, "No internet, cannot update");
 | 
				
			||||||
                if (manualUpdate) {
 | 
					                if (manualUpdate) {
 | 
				
			||||||
                    sendNoInternetToast();
 | 
					                    sendNoInternetToast();
 | 
				
			||||||
@ -380,10 +348,10 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            final Preferences fdroidPrefs = Preferences.get();
 | 
				
			||||||
            if (manualUpdate || forcedUpdate) {
 | 
					            if (manualUpdate || forcedUpdate) {
 | 
				
			||||||
                Utils.debugLog(TAG, "manually requested or forced update");
 | 
					                Utils.debugLog(TAG, "manually requested or forced update");
 | 
				
			||||||
            } else if (!verifyIsTimeForScheduledRun()
 | 
					            } else if (!verifyIsTimeForScheduledRun() || !fdroidPrefs.isBackgroundDownloadAllowed()) {
 | 
				
			||||||
                    || (netState == FLAG_NET_METERED && Preferences.get().isUpdateOnlyOnUnmeteredNetworks())) {
 | 
					 | 
				
			||||||
                Utils.debugLog(TAG, "don't run update");
 | 
					                Utils.debugLog(TAG, "don't run update");
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -403,7 +371,6 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
            ArrayList<CharSequence> repoErrors = new ArrayList<>();
 | 
					            ArrayList<CharSequence> repoErrors = new ArrayList<>();
 | 
				
			||||||
            boolean changes = false;
 | 
					            boolean changes = false;
 | 
				
			||||||
            boolean singleRepoUpdate = !TextUtils.isEmpty(address);
 | 
					            boolean singleRepoUpdate = !TextUtils.isEmpty(address);
 | 
				
			||||||
            final Preferences fdroidPrefs = Preferences.get();
 | 
					 | 
				
			||||||
            for (final Repo repo : repos) {
 | 
					            for (final Repo repo : repos) {
 | 
				
			||||||
                if (!repo.inuse) {
 | 
					                if (!repo.inuse) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
@ -442,7 +409,7 @@ public class UpdateService extends IntentService {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // now that downloading the index is done, start downloading updates
 | 
					                // now that downloading the index is done, start downloading updates
 | 
				
			||||||
                if (changes && fdroidPrefs.isAutoDownloadEnabled()) {
 | 
					                if (changes && fdroidPrefs.isAutoDownloadEnabled() && fdroidPrefs.isBackgroundDownloadAllowed()) {
 | 
				
			||||||
                    autoDownloadUpdates(this);
 | 
					                    autoDownloadUpdates(this);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -406,6 +406,12 @@ public final class Utils {
 | 
				
			|||||||
        return new Locale(languageTag);
 | 
					        return new Locale(languageTag);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Since there have been vulnerabilities in EXIF processing in Android, this
 | 
				
			||||||
 | 
					     * disables all use of EXIF.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @see <a href="https://securityaffairs.co/wordpress/51043/mobile-2/android-cve-2016-3862-flaw.html">CVE-2016-3862</a>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public static DisplayImageOptions.Builder getDefaultDisplayImageOptionsBuilder() {
 | 
					    public static DisplayImageOptions.Builder getDefaultDisplayImageOptionsBuilder() {
 | 
				
			||||||
        if (defaultDisplayImageOptionsBuilder == null) {
 | 
					        if (defaultDisplayImageOptionsBuilder == null) {
 | 
				
			||||||
            defaultDisplayImageOptionsBuilder = new DisplayImageOptions.Builder()
 | 
					            defaultDisplayImageOptionsBuilder = new DisplayImageOptions.Builder()
 | 
				
			||||||
 | 
				
			|||||||
@ -106,19 +106,23 @@ public abstract class Installer {
 | 
				
			|||||||
        return intent;
 | 
					        return intent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Return if this installation process has any new permissions that the user
 | 
				
			||||||
 | 
					     * should be aware of.  Starting in {@code android-23}, all new permissions
 | 
				
			||||||
 | 
					     * are requested when they are used, and the permissions prompt at time of
 | 
				
			||||||
 | 
					     * install is not used.  All permissions in a new install are considered new.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return the number of new permissions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private int newPermissionCount() {
 | 
					    private int newPermissionCount() {
 | 
				
			||||||
        boolean supportsRuntimePermissions = apk.targetSdkVersion >= 23;
 | 
					        boolean supportsRuntimePermissions = apk.targetSdkVersion >= 23;
 | 
				
			||||||
        if (supportsRuntimePermissions) {
 | 
					        if (supportsRuntimePermissions) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AppDiff appDiff = new AppDiff(context.getPackageManager(), apk);
 | 
					        AppDiff appDiff = new AppDiff(context, apk);
 | 
				
			||||||
        if (appDiff.pkgInfo == null) {
 | 
					        AppSecurityPermissions perms = new AppSecurityPermissions(context, appDiff.apkPackageInfo);
 | 
				
			||||||
            // could not get diff because we couldn't parse the package
 | 
					        if (appDiff.installedApplicationInfo != null) {
 | 
				
			||||||
            throw new RuntimeException("cannot parse!");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        AppSecurityPermissions perms = new AppSecurityPermissions(context, appDiff.pkgInfo);
 | 
					 | 
				
			||||||
        if (appDiff.installedAppInfo != null) {
 | 
					 | 
				
			||||||
            // update to an existing app
 | 
					            // update to an existing app
 | 
				
			||||||
            return perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW);
 | 
					            return perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					package org.fdroid.fdroid.net;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.app.IntentService;
 | 
				
			||||||
 | 
					import android.content.BroadcastReceiver;
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					import android.content.Intent;
 | 
				
			||||||
 | 
					import android.content.IntentFilter;
 | 
				
			||||||
 | 
					import android.net.ConnectivityManager;
 | 
				
			||||||
 | 
					import android.net.NetworkInfo;
 | 
				
			||||||
 | 
					import android.os.Build;
 | 
				
			||||||
 | 
					import com.nostra13.universalimageloader.core.ImageLoader;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.FDroidApp;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.Preferences;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An {@link IntentService} subclass for tracking whether there is metered or
 | 
				
			||||||
 | 
					 * unmetered internet available, based on
 | 
				
			||||||
 | 
					 * {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class ConnectivityMonitorService extends IntentService {
 | 
				
			||||||
 | 
					    public static final String TAG = "ConnectivityMonitorServ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final int FLAG_NET_UNAVAILABLE = 0;
 | 
				
			||||||
 | 
					    public static final int FLAG_NET_METERED = 1;
 | 
				
			||||||
 | 
					    public static final int FLAG_NET_NO_LIMIT = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final String ACTION_START = "org.fdroid.fdroid.net.action.CONNECTIVITY_MONITOR";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final BroadcastReceiver CONNECTIVITY_RECEIVER = new BroadcastReceiver() {
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void onReceive(Context context, Intent intent) {
 | 
				
			||||||
 | 
					            start(context);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ConnectivityMonitorService() {
 | 
				
			||||||
 | 
					        super("ConnectivityMonitorService");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void registerAndStart(Context context) {
 | 
				
			||||||
 | 
					        context.registerReceiver(CONNECTIVITY_RECEIVER, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void start(Context context) {
 | 
				
			||||||
 | 
					        Intent intent = new Intent(context, ConnectivityMonitorService.class);
 | 
				
			||||||
 | 
					        intent.setAction(ACTION_START);
 | 
				
			||||||
 | 
					        context.startService(intent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 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.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static int getNetworkState(Context context) {
 | 
				
			||||||
 | 
					        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
 | 
				
			||||||
 | 
					        if (cm == null) {
 | 
				
			||||||
 | 
					            return FLAG_NET_UNAVAILABLE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
 | 
				
			||||||
 | 
					        if (activeNetwork == null || !activeNetwork.isConnected()) {
 | 
				
			||||||
 | 
					            return FLAG_NET_UNAVAILABLE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int networkType = activeNetwork.getType();
 | 
				
			||||||
 | 
					        switch (networkType) {
 | 
				
			||||||
 | 
					            case ConnectivityManager.TYPE_ETHERNET:
 | 
				
			||||||
 | 
					            case ConnectivityManager.TYPE_WIFI:
 | 
				
			||||||
 | 
					                if (Build.VERSION.SDK_INT >= 16 && cm.isActiveNetworkMetered()) {
 | 
				
			||||||
 | 
					                    return FLAG_NET_METERED;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return FLAG_NET_NO_LIMIT;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return FLAG_NET_METERED;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onHandleIntent(Intent intent) {
 | 
				
			||||||
 | 
					        if (intent != null && ACTION_START.equals(intent.getAction())) {
 | 
				
			||||||
 | 
					            FDroidApp.networkState = getNetworkState(this);
 | 
				
			||||||
 | 
					            ImageLoader.getInstance().denyNetworkDownloads(!Preferences.get().isBackgroundDownloadAllowed());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -18,55 +18,51 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package org.fdroid.fdroid.privileged.views;
 | 
					package org.fdroid.fdroid.privileged.views;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
import android.content.pm.ApplicationInfo;
 | 
					import android.content.pm.ApplicationInfo;
 | 
				
			||||||
import android.content.pm.PackageInfo;
 | 
					import android.content.pm.PackageInfo;
 | 
				
			||||||
import android.content.pm.PackageManager;
 | 
					import android.content.pm.PackageManager;
 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.fdroid.fdroid.data.Apk;
 | 
					import org.fdroid.fdroid.data.Apk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Represents the permissions difference between the installed APK, and the
 | 
				
			||||||
 | 
					 * update APK represented by {@link Apk}.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class AppDiff {
 | 
					public class AppDiff {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final PackageManager pm;
 | 
					    public final PackageInfo apkPackageInfo;
 | 
				
			||||||
    public final PackageInfo pkgInfo;
 | 
					    public final ApplicationInfo installedApplicationInfo;
 | 
				
			||||||
    public ApplicationInfo installedAppInfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public AppDiff(Context context, Apk apk) {
 | 
				
			||||||
     * Constructor based on F-Droids Apk object
 | 
					        PackageManager pm = context.getPackageManager();
 | 
				
			||||||
     */
 | 
					        apkPackageInfo = new PackageInfo();
 | 
				
			||||||
    public AppDiff(PackageManager pm, Apk apk) {
 | 
					        apkPackageInfo.packageName = apk.packageName;
 | 
				
			||||||
        this.pm = pm;
 | 
					        apkPackageInfo.applicationInfo = new ApplicationInfo();
 | 
				
			||||||
 | 
					        apkPackageInfo.requestedPermissions = apk.requestedPermissions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pkgInfo = new PackageInfo();
 | 
					        String packageName = apkPackageInfo.packageName;
 | 
				
			||||||
        pkgInfo.packageName = apk.packageName;
 | 
					 | 
				
			||||||
        pkgInfo.applicationInfo = new ApplicationInfo();
 | 
					 | 
				
			||||||
        pkgInfo.requestedPermissions = apk.requestedPermissions;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        init();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void init() {
 | 
					 | 
				
			||||||
        String pkgName = pkgInfo.packageName;
 | 
					 | 
				
			||||||
        // Check if there is already a package on the device with this name
 | 
					        // Check if there is already a package on the device with this name
 | 
				
			||||||
        // but it has been renamed to something else.
 | 
					        // but it has been renamed to something else.
 | 
				
			||||||
        final String[] oldName = pm.canonicalToCurrentPackageNames(new String[]{pkgName});
 | 
					        final String[] oldName = pm.canonicalToCurrentPackageNames(new String[]{packageName});
 | 
				
			||||||
        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
 | 
					        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
 | 
				
			||||||
            pkgName = oldName[0];
 | 
					            packageName = oldName[0];
 | 
				
			||||||
            pkgInfo.packageName = pkgName;
 | 
					            apkPackageInfo.packageName = packageName;
 | 
				
			||||||
            pkgInfo.applicationInfo.packageName = pkgName;
 | 
					            apkPackageInfo.applicationInfo.packageName = packageName;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Check if package is already installed
 | 
					        // Check if package is already installed
 | 
				
			||||||
 | 
					        ApplicationInfo applicationInfo;
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            // This is a little convoluted because we want to get all uninstalled
 | 
					            // This is a little convoluted because we want to get all uninstalled
 | 
				
			||||||
            // apps, but this may include apps with just data, and if it is just
 | 
					            // apps, but this may include apps with just data, and if it is just
 | 
				
			||||||
            // data we still want to count it as "installed".
 | 
					            // data we still want to count it as "installed".
 | 
				
			||||||
            //noinspection WrongConstant (lint is actually wrong here!)
 | 
					            //noinspection WrongConstant (lint is actually wrong here!)
 | 
				
			||||||
            installedAppInfo = pm.getApplicationInfo(pkgName,
 | 
					            applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
 | 
				
			||||||
                    PackageManager.GET_UNINSTALLED_PACKAGES);
 | 
					            if ((applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
 | 
				
			||||||
            if ((installedAppInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
 | 
					                applicationInfo = null;
 | 
				
			||||||
                installedAppInfo = null;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (PackageManager.NameNotFoundException e) {
 | 
					        } catch (PackageManager.NameNotFoundException e) {
 | 
				
			||||||
            installedAppInfo = null;
 | 
					            applicationInfo = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        installedApplicationInfo = applicationInfo;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -92,9 +92,9 @@ public class InstallConfirmActivity extends FragmentActivity implements OnCancel
 | 
				
			|||||||
        scrollView = null;
 | 
					        scrollView = null;
 | 
				
			||||||
        okCanInstall = false;
 | 
					        okCanInstall = false;
 | 
				
			||||||
        int msg = 0;
 | 
					        int msg = 0;
 | 
				
			||||||
        AppSecurityPermissions perms = new AppSecurityPermissions(this, appDiff.pkgInfo);
 | 
					        AppSecurityPermissions perms = new AppSecurityPermissions(this, appDiff.apkPackageInfo);
 | 
				
			||||||
        if (appDiff.installedAppInfo != null) {
 | 
					        if (appDiff.installedApplicationInfo != null) {
 | 
				
			||||||
            msg = (appDiff.installedAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
 | 
					            msg = (appDiff.installedApplicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
 | 
				
			||||||
                    ? R.string.install_confirm_update_system
 | 
					                    ? R.string.install_confirm_update_system
 | 
				
			||||||
                    : R.string.install_confirm_update;
 | 
					                    : R.string.install_confirm_update;
 | 
				
			||||||
            scrollView = new CaffeinatedScrollView(this);
 | 
					            scrollView = new CaffeinatedScrollView(this);
 | 
				
			||||||
@ -131,10 +131,10 @@ public class InstallConfirmActivity extends FragmentActivity implements OnCancel
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!permVisible) {
 | 
					        if (!permVisible) {
 | 
				
			||||||
            if (appDiff.installedAppInfo != null) {
 | 
					            if (appDiff.installedApplicationInfo != null) {
 | 
				
			||||||
                // This is an update to an application, but there are no
 | 
					                // This is an update to an application, but there are no
 | 
				
			||||||
                // permissions at all.
 | 
					                // permissions at all.
 | 
				
			||||||
                msg = (appDiff.installedAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
 | 
					                msg = (appDiff.installedApplicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
 | 
				
			||||||
                        ? R.string.install_confirm_update_system_no_perms
 | 
					                        ? R.string.install_confirm_update_system_no_perms
 | 
				
			||||||
                        : R.string.install_confirm_update_no_perms;
 | 
					                        : R.string.install_confirm_update_no_perms;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@ -182,7 +182,7 @@ public class InstallConfirmActivity extends FragmentActivity implements OnCancel
 | 
				
			|||||||
        app = AppProvider.Helper.findSpecificApp(getContentResolver(),
 | 
					        app = AppProvider.Helper.findSpecificApp(getContentResolver(),
 | 
				
			||||||
                apk.packageName, apk.repoId, Schema.AppMetadataTable.Cols.ALL);
 | 
					                apk.packageName, apk.repoId, Schema.AppMetadataTable.Cols.ALL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        appDiff = new AppDiff(getPackageManager(), apk);
 | 
					        appDiff = new AppDiff(this, apk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setContentView(R.layout.install_start);
 | 
					        setContentView(R.layout.install_start);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -789,8 +789,8 @@ public class AppDetailsRecyclerViewAdapter
 | 
				
			|||||||
            headerView.setText(R.string.permissions);
 | 
					            headerView.setText(R.string.permissions);
 | 
				
			||||||
            updateExpandableItem(false);
 | 
					            updateExpandableItem(false);
 | 
				
			||||||
            contentView.removeAllViews();
 | 
					            contentView.removeAllViews();
 | 
				
			||||||
            AppDiff appDiff = new AppDiff(context.getPackageManager(), versions.get(0));
 | 
					            AppDiff appDiff = new AppDiff(context, versions.get(0));
 | 
				
			||||||
            AppSecurityPermissions perms = new AppSecurityPermissions(context, appDiff.pkgInfo);
 | 
					            AppSecurityPermissions perms = new AppSecurityPermissions(context, appDiff.apkPackageInfo);
 | 
				
			||||||
            contentView.addView(perms.getPermissionsView(AppSecurityPermissions.WHICH_ALL));
 | 
					            contentView.addView(perms.getPermissionsView(AppSecurityPermissions.WHICH_ALL));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ import android.widget.ImageView;
 | 
				
			|||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
 | 
					import com.nostra13.universalimageloader.core.DisplayImageOptions;
 | 
				
			||||||
import com.nostra13.universalimageloader.core.ImageLoader;
 | 
					import com.nostra13.universalimageloader.core.ImageLoader;
 | 
				
			||||||
import org.fdroid.fdroid.FDroidApp;
 | 
					import org.fdroid.fdroid.FDroidApp;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.Preferences;
 | 
				
			||||||
import org.fdroid.fdroid.R;
 | 
					import org.fdroid.fdroid.R;
 | 
				
			||||||
import org.fdroid.fdroid.Utils;
 | 
					import org.fdroid.fdroid.Utils;
 | 
				
			||||||
import org.fdroid.fdroid.data.App;
 | 
					import org.fdroid.fdroid.data.App;
 | 
				
			||||||
@ -36,6 +37,8 @@ public class ScreenShotsActivity extends AppCompatActivity {
 | 
				
			|||||||
    private static final String EXTRA_PACKAGE_NAME = "EXTRA_PACKAGE_NAME";
 | 
					    private static final String EXTRA_PACKAGE_NAME = "EXTRA_PACKAGE_NAME";
 | 
				
			||||||
    private static final String EXTRA_START_POSITION = "EXTRA_START_POSITION";
 | 
					    private static final String EXTRA_START_POSITION = "EXTRA_START_POSITION";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final ImageLoader IMAGE_LOADER = ImageLoader.getInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Intent getStartIntent(Context context, String packageName, int startPosition) {
 | 
					    public static Intent getStartIntent(Context context, String packageName, int startPosition) {
 | 
				
			||||||
        Intent intent = new Intent(context, ScreenShotsActivity.class);
 | 
					        Intent intent = new Intent(context, ScreenShotsActivity.class);
 | 
				
			||||||
        intent.putExtra(EXTRA_PACKAGE_NAME, packageName);
 | 
					        intent.putExtra(EXTRA_PACKAGE_NAME, packageName);
 | 
				
			||||||
@ -68,6 +71,18 @@ public class ScreenShotsActivity extends AppCompatActivity {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onResume() {
 | 
				
			||||||
 | 
					        super.onResume();
 | 
				
			||||||
 | 
					        IMAGE_LOADER.denyNetworkDownloads(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onPause() {
 | 
				
			||||||
 | 
					        super.onPause();
 | 
				
			||||||
 | 
					        IMAGE_LOADER.denyNetworkDownloads(!Preferences.get().isBackgroundDownloadAllowed());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static class ScreenShotPagerAdapter extends FragmentStatePagerAdapter {
 | 
					    private static class ScreenShotPagerAdapter extends FragmentStatePagerAdapter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private final String[] screenshots;
 | 
					        private final String[] screenshots;
 | 
				
			||||||
 | 
				
			|||||||
@ -568,4 +568,12 @@
 | 
				
			|||||||
    <string name="force_touch_apps">Inclue sas aplicatziones chi impreant s\'ischermu tàtile</string>
 | 
					    <string name="force_touch_apps">Inclue sas aplicatziones chi impreant s\'ischermu tàtile</string>
 | 
				
			||||||
    <string name="force_touch_apps_on">Ammustra sas aplicatziones chi tenent bisòngiu de s\'ischermu tàtile in cale si siat dispositivu</string>
 | 
					    <string name="force_touch_apps_on">Ammustra sas aplicatziones chi tenent bisòngiu de s\'ischermu tàtile in cale si siat dispositivu</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <string name="repo_add_mirror">Annanghe un\'ispigru</string>
 | 
				
			||||||
 | 
					    <string name="repo_exists_add_fingerprint">%1$s est giai impostadu, custu at a annànghere informatziones de crae noas.</string>
 | 
				
			||||||
 | 
					    <string name="repo_exists_enable">%1$s est giai impostadu, cunfirma chi lu cheres torrare a abilitare.</string>
 | 
				
			||||||
 | 
					    <string name="repo_exists_and_enabled">%1$s est giai impostadu e abilitadu.</string>
 | 
				
			||||||
 | 
					    <string name="repo_delete_to_overwrite">In antis iscantzella %1$s pro annànghere custu cun una crae in cunflitu.</string>
 | 
				
			||||||
 | 
					    <string name="repo_exists_add_mirror">Custa est una còpia de %1$s, lu cheres annànghere comente isprigu?</string>
 | 
				
			||||||
 | 
					    <string name="repo_official_mirrors">Isprigos ufitziales</string>
 | 
				
			||||||
 | 
					    <string name="repo_user_mirrors">Isprigos impreadores</string>
 | 
				
			||||||
    </resources>
 | 
					    </resources>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user