diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2e9d78a04..7d2503634 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -258,6 +258,10 @@
+
diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateJobService.java b/app/src/main/java/org/fdroid/fdroid/UpdateJobService.java
new file mode 100644
index 000000000..73561ce19
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/UpdateJobService.java
@@ -0,0 +1,43 @@
+package org.fdroid.fdroid;
+
+import android.annotation.TargetApi;
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.content.Intent;
+
+/**
+ * Interface between the new {@link android.app.job.JobScheduler} API and
+ * our old {@link UpdateService}, which is based on {@link android.app.IntentService}.
+ * This does not do things the way it should, e.g. stopping the job on
+ * {@link #onStopJob(JobParameters)} and properly reporting
+ * {@link #jobFinished(JobParameters, boolean)}, but this at least provides
+ * the nice early triggering when there is good power/wifi available.
+ *
+ * @see Project Volta: Scheduling jobs
+ */
+@TargetApi(21)
+public class UpdateJobService extends JobService {
+ @Override
+ public boolean onStartJob(final JobParameters params) {
+ new Thread() {
+ @Override
+ public void run() {
+ // faking the actually run time
+ try {
+ startService(new Intent(UpdateJobService.this, UpdateService.class));
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ // ignored
+ } finally {
+ jobFinished(params, false);
+ }
+ }
+ }.start();
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ return false;
+ }
+}
diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java
index b30cbc13d..73f7591cd 100644
--- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java
+++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java
@@ -22,7 +22,10 @@ import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -118,27 +121,41 @@ public class UpdateService extends IntentService {
}
/**
- * Schedule or cancel this service to update the app index, according to the
- * current preferences. Should be called a) at boot, b) if the preference
- * is changed, or c) on startup, in case we get upgraded.
+ * Schedule this service to update the app index while canceling any previously
+ * scheduled updates, according to the current preferences. Should be called
+ * a) at boot, b) if the preference is changed, or c) on startup, in case we get
+ * upgraded. It works differently on {@code android-21} and newer, versus older,
+ * due to the {@link JobScheduler} API handling it very nicely for us.
+ *
+ * @see Project Volta: Scheduling jobs
*/
- public static void schedule(Context ctx) {
+ public static void schedule(Context context) {
int interval = Preferences.get().getUpdateInterval();
- Intent intent = new Intent(ctx, UpdateService.class);
- PendingIntent pending = PendingIntent.getService(ctx, 0, intent, 0);
+ if (Build.VERSION.SDK_INT < 21) {
+ Intent intent = new Intent(context, UpdateService.class);
+ PendingIntent pending = PendingIntent.getService(context, 0, intent, 0);
- AlarmManager alarm = (AlarmManager) ctx
- .getSystemService(Context.ALARM_SERVICE);
- alarm.cancel(pending);
- if (interval > 0) {
- alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
- SystemClock.elapsedRealtime() + 5000, interval, pending);
- Utils.debugLog(TAG, "Update scheduler alarm set");
+ AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ alarm.cancel(pending);
+ if (interval > 0) {
+ alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
+ SystemClock.elapsedRealtime() + 5000, interval, pending);
+ Utils.debugLog(TAG, "Update scheduler alarm set");
+ } else {
+ Utils.debugLog(TAG, "Update scheduler alarm not set");
+ }
} else {
- Utils.debugLog(TAG, "Update scheduler alarm not set");
+ Utils.debugLog(TAG, "Using android-21 JobScheduler for updates");
+ JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+ jobScheduler.cancelAll();
+ ComponentName componentName = new ComponentName(context, UpdateJobService.class);
+ JobInfo task = new JobInfo.Builder(0xfedcba, componentName)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
+ .setOverrideDeadline(interval)
+ .build();
+ jobScheduler.schedule(task);
}
-
}
/**