move update scheduling entirely to AlarmManager

This changes the flow of the update triggering so that any Intent sent to
UpdateService can potentially trigger an update, depending only on the
state of the internet and the "Only on WiFi" preference.  Instead of having
a timer that checks every hour to see if it is time to run the update, just
let AlarmManager send a trigger Intent based on the timing in the
"Update Interval" setting.

The update schedule is reset each time F-Droid restarts, and also each time
the user returns from the settings, so if AlarmManager fails us in the time
being, the updates will be rescheduled next time F-Droid is restarted, the
device is rebooted, etc.

refs #662
This commit is contained in:
Hans-Christoph Steiner 2016-11-10 20:40:23 +01:00
parent 5f3e952958
commit 7d9f5e880c
2 changed files with 11 additions and 37 deletions

View File

@ -158,14 +158,19 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
*/
private static final String PREF_CACHE_APK = "cacheDownloaded";
/**
* Get the update interval in milliseconds.
*/
public int getUpdateInterval() {
int hours;
try {
String value = preferences.getString(PREF_UPD_INTERVAL,
String.valueOf(DEFAULT_UPD_INTERVAL));
return Integer.parseInt(value);
hours = Integer.parseInt(value);
} catch (NumberFormatException e) {
return DEFAULT_UPD_INTERVAL;
hours = DEFAULT_UPD_INTERVAL;
}
return hours * 60 * 60 * 1000;
}
/**

View File

@ -131,8 +131,7 @@ public class UpdateService extends IntentService {
alarm.cancel(pending);
if (interval > 0) {
alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 5000,
AlarmManager.INTERVAL_HOUR, pending);
SystemClock.elapsedRealtime() + 5000, interval, pending);
Utils.debugLog(TAG, "Update scheduler alarm set");
} else {
Utils.debugLog(TAG, "Update scheduler alarm not set");
@ -275,34 +274,6 @@ public class UpdateService extends IntentService {
}
};
/**
* Check whether it is time to run the scheduled update.
* We don't want to run if:
* - The time between scheduled runs is set to zero (though don't know
* when that would occur)
* - Last update was too recent
* - Not on wifi, but the property for "Only auto update on wifi" is set.
*
* @return True if we are due for a scheduled update.
*/
private boolean verifyIsTimeForScheduledRun() {
int interval = Preferences.get().getUpdateInterval();
if (interval == 0) {
Log.i(TAG, "Skipping update - disabled");
return false;
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
long lastUpdate = prefs.getLong(STATE_LAST_UPDATED, 0);
long elapsed = System.currentTimeMillis() - lastUpdate;
if (elapsed < interval * 60 * 60 * 1000) {
Log.i(TAG, "Skipping update - done " + elapsed
+ "ms ago, interval is " + interval + " hours");
return false;
}
return true;
}
/**
* In order to send a {@link Toast} from a {@link IntentService}, we have to do these tricks.
*/
@ -334,6 +305,7 @@ public class UpdateService extends IntentService {
}
try {
final Preferences fdroidPrefs = Preferences.get();
// See if it's time to actually do anything yet...
int netState = ConnectivityMonitorService.getNetworkState(this);
if (address != null && address.startsWith(BluetoothDownloader.SCHEME)) {
@ -344,12 +316,9 @@ public class UpdateService extends IntentService {
sendNoInternetToast();
}
return;
}
final Preferences fdroidPrefs = Preferences.get();
if (manualUpdate || forcedUpdate) {
} else if (manualUpdate || forcedUpdate) {
Utils.debugLog(TAG, "manually requested or forced update");
} else if (!verifyIsTimeForScheduledRun() || !fdroidPrefs.isBackgroundDownloadAllowed()) {
} else if (!fdroidPrefs.isBackgroundDownloadAllowed()) {
Utils.debugLog(TAG, "don't run update");
return;
}