Merge branch 'rework-net-for-0.102' into 'master'

Rework net for 0.102

This is a collection of targeted fixes for the %"0.102" release.  Most of them are quite narrowly targeted bug fixes.  I couldn't avoid reworking the update scheduling in order to fix some of the listed bugs.  This is the only part that seems possible to have regressions.  In any case, if there are regressions, they will be in a very limited chunk of the code, in `UpdateService`, which we have no plans to touch in %"0.103 - UX Overhaul" so it'll be easy to do a 0.102.1 release.

See merge request !415
This commit is contained in:
Peter Serwylo 2016-11-16 21:19:15 +00:00
commit 35996952ef
6 changed files with 104 additions and 27 deletions

View File

@ -1525,8 +1525,10 @@ public class AppDetails extends AppCompatActivity {
public void startProgress(boolean allowCancel) { public void startProgress(boolean allowCancel) {
cancelButton.setVisibility(allowCancel ? View.VISIBLE : View.GONE); cancelButton.setVisibility(allowCancel ? View.VISIBLE : View.GONE);
showIndeterminateProgress(getString(R.string.download_pending)); if (isAdded()) {
updateViews(); showIndeterminateProgress(getString(R.string.download_pending));
updateViews();
}
} }
private void showIndeterminateProgress(String message) { private void showIndeterminateProgress(String message) {

View File

@ -231,7 +231,7 @@ 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 isUpdateOnlyOnWifi() { public boolean isUpdateOnlyOnUnmeteredNetworks() {
return preferences.getBoolean(PREF_UPD_WIFI_ONLY, false); return preferences.getBoolean(PREF_UPD_WIFI_ONLY, false);
} }

View File

@ -31,6 +31,8 @@ import android.database.Cursor;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Process; import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.preference.PreferenceManager; 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_UPDATING = 0;
private static final int NOTIFY_ID_UPDATES_AVAILABLE = 1; 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 NotificationManager notificationManager;
private NotificationCompat.Builder notificationBuilder; private NotificationCompat.Builder notificationBuilder;
@ -279,26 +287,50 @@ public class UpdateService extends IntentService {
return false; 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); ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// this could be cellular or wifi
NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork == null) { if (activeNetwork == null || !activeNetwork.isConnected()) {
return false; return FLAG_NET_UNAVAILABLE;
} }
if (activeNetwork.getType() != ConnectivityManager.TYPE_WIFI && Preferences.get().isUpdateOnlyOnWifi()) { int networkType = activeNetwork.getType();
Log.i(TAG, "Skipping update - wifi not available"); switch (networkType) {
return false; 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;
} }
return activeNetwork.isConnectedOrConnecting(); }
/**
* 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 @Override
@ -315,9 +347,20 @@ 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);
if (netState == FLAG_NET_UNAVAILABLE) {
Utils.debugLog(TAG, "No internet, cannot update");
if (manualUpdate) {
sendNoInternetToast();
}
return;
}
if (manualUpdate) { if (manualUpdate) {
Utils.debugLog(TAG, "Unscheduled (manually requested) update"); Utils.debugLog(TAG, "manually requested update");
} else if (!verifyIsTimeForScheduledRun()) { } else if (!verifyIsTimeForScheduledRun()
|| (netState == FLAG_NET_METERED && Preferences.get().isUpdateOnlyOnUnmeteredNetworks())) {
Utils.debugLog(TAG, "don't run update");
return; return;
} }

View File

@ -11,11 +11,13 @@ import android.net.Uri;
import android.os.Process; import android.os.Process;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import org.acra.ACRA;
import org.fdroid.fdroid.Hasher; import org.fdroid.fdroid.Hasher;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Schema.InstalledAppTable; import org.fdroid.fdroid.data.Schema.InstalledAppTable;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -154,24 +156,49 @@ public class InstalledAppProviderService extends IntentService {
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
if (intent != null) { if (intent == null) {
String packageName = intent.getData().getSchemeSpecificPart(); return;
final String action = intent.getAction(); }
if (ACTION_INSERT.equals(action)) {
PackageInfo packageInfo = getPackageInfo(intent, packageName); String packageName = intent.getData().getSchemeSpecificPart();
if (packageInfo != null) { final String action = intent.getAction();
File apk = new File(packageInfo.applicationInfo.publicSourceDir); if (ACTION_INSERT.equals(action)) {
if (apk.exists() && apk.canRead()) { PackageInfo packageInfo = getPackageInfo(intent, packageName);
if (packageInfo != null) {
File apk = new File(packageInfo.applicationInfo.publicSourceDir);
if (apk.isDirectory()) {
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".apk");
}
};
File[] files = apk.listFiles(filter);
if (files == null) {
String msg = packageName + " sourceDir has no APKs: "
+ apk.getAbsolutePath();
Utils.debugLog(TAG, msg);
ACRA.getErrorReporter().handleException(new IllegalArgumentException(msg), false);
return;
}
apk = files[0];
}
if (apk.exists() && apk.canRead()) {
try {
String hashType = "sha256"; String hashType = "sha256";
String hash = Utils.getBinaryHash(apk, hashType); String hash = Utils.getBinaryHash(apk, hashType);
insertAppIntoDb(this, packageInfo, hashType, hash); insertAppIntoDb(this, packageInfo, hashType, hash);
} catch (IllegalArgumentException e) {
Utils.debugLog(TAG, e.getMessage());
ACRA.getErrorReporter().handleException(e, false);
return;
} }
} }
} else if (ACTION_DELETE.equals(action)) {
deleteAppFromDb(this, packageName);
} }
notifyEvents.onNext(null); } else if (ACTION_DELETE.equals(action)) {
deleteAppFromDb(this, packageName);
} }
notifyEvents.onNext(null);
} }
/** /**

View File

@ -3,6 +3,7 @@ package org.fdroid.fdroid.net;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader; import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.fdroid.fdroid.BuildConfig;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.spongycastle.util.encoders.Base64; import org.spongycastle.util.encoders.Base64;
@ -83,6 +84,7 @@ public class HttpDownloader extends Downloader {
// get the file size from the server // get the file size from the server
HttpURLConnection tmpConn = getConnection(); HttpURLConnection tmpConn = getConnection();
tmpConn.setRequestMethod("HEAD");
int contentLength = -1; int contentLength = -1;
if (tmpConn.getResponseCode() == 200) { if (tmpConn.getResponseCode() == 200) {
contentLength = tmpConn.getContentLength(); contentLength = tmpConn.getContentLength();
@ -115,6 +117,8 @@ public class HttpDownloader extends Downloader {
connection = NetCipher.getHttpURLConnection(sourceUrl); connection = NetCipher.getHttpURLConnection(sourceUrl);
} }
connection.setRequestProperty("User-Agent", "F-Droid " + BuildConfig.VERSION_NAME);
if (username != null && password != null) { if (username != null && password != null) {
// add authorization header from username / password if set // add authorization header from username / password if set
String authString = username + ":" + password; String authString = username + ":" + password;

View File

@ -21,7 +21,7 @@
<string name="update_interval">Automatic update interval</string> <string name="update_interval">Automatic update interval</string>
<string name="update_interval_zero">No automatic app list updates</string> <string name="update_interval_zero">No automatic app list updates</string>
<string name="automatic_scan_wifi">Only on Wi-Fi</string> <string name="automatic_scan_wifi">Only on Wi-Fi</string>
<string name="automatic_scan_wifi_on">Update app lists automatically only on Wi-Fi</string> <string name="automatic_scan_wifi_on">Only update automatically on unmetered networks like Wi-Fi</string>
<string name="update_auto_download">Automatically download updates</string> <string name="update_auto_download">Automatically download updates</string>
<string name="update_auto_download_summary">Download the update files in the background</string> <string name="update_auto_download_summary">Download the update files in the background</string>
<string name="update_auto_install">Automatically install updates</string> <string name="update_auto_install">Automatically install updates</string>
@ -201,6 +201,7 @@
<string name="repos_unchanged">All repositories are up to date</string> <string name="repos_unchanged">All repositories are up to date</string>
<string name="all_other_repos_fine">All other repos didn\'t create errors.</string> <string name="all_other_repos_fine">All other repos didn\'t create errors.</string>
<string name="global_error_updating_repos">Error during update: %s</string> <string name="global_error_updating_repos">Error during update: %s</string>
<string name="warning_no_internet">Cannot update, are you connected to the internet?</string>
<string name="no_permissions">No permissions are used.</string> <string name="no_permissions">No permissions are used.</string>
<string name="permissions">Permissions</string> <string name="permissions">Permissions</string>
<string name="no_handler_app">You don\'t have any available app that can handle %s.</string> <string name="no_handler_app">You don\'t have any available app that can handle %s.</string>