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); } - } /**