switch UpdateService to a JobIntentService

closes #1426
This commit is contained in:
Hans-Christoph Steiner 2018-04-24 21:09:36 +02:00
parent fe260d931c
commit 07ada4e6b2
4 changed files with 30 additions and 41 deletions

View File

@ -252,7 +252,10 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<service android:name=".UpdateService"/> <service
android:name=".UpdateService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service <service
android:name=".UpdateJobService" android:name=".UpdateJobService"
android:exported="false" android:exported="false"

View File

@ -3,15 +3,10 @@ package org.fdroid.fdroid;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.job.JobParameters; import android.app.job.JobParameters;
import android.app.job.JobService; import android.app.job.JobService;
import android.content.Intent;
/** /**
* Interface between the new {@link android.app.job.JobScheduler} API and * Interface between the new {@link android.app.job.JobScheduler} API and
* our old {@link UpdateService}, which is based on {@link android.app.IntentService}. * {@link UpdateService}, which is based on {@link android.support.v4.app.JobIntentService}.
* 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 <a href="https://developer.android.com/about/versions/android-5.0.html#Power">Project Volta: Scheduling jobs</a> * @see <a href="https://developer.android.com/about/versions/android-5.0.html#Power">Project Volta: Scheduling jobs</a>
*/ */
@ -19,25 +14,13 @@ import android.content.Intent;
public class UpdateJobService extends JobService { public class UpdateJobService extends JobService {
@Override @Override
public boolean onStartJob(final JobParameters params) { public boolean onStartJob(final JobParameters params) {
new Thread() { UpdateService.updateNow(this);
@Override return false;
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 @Override
public boolean onStopJob(JobParameters params) { public boolean onStopJob(JobParameters params) {
return false; // TODO this should gracefully stop UpdateService
return true;
} }
} }

View File

@ -37,6 +37,8 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Process; import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceManager;
@ -60,7 +62,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class UpdateService extends IntentService { public class UpdateService extends JobIntentService {
private static final String TAG = "UpdateService"; private static final String TAG = "UpdateService";
@ -81,6 +83,7 @@ public class UpdateService extends IntentService {
public static final int STATUS_INFO = 5; public static final int STATUS_INFO = 5;
private static final String STATE_LAST_UPDATED = "lastUpdateCheck"; private static final String STATE_LAST_UPDATED = "lastUpdateCheck";
private static final int JOB_ID = 0xfedcba;
private static final int NOTIFY_ID_UPDATING = 0; private static final int NOTIFY_ID_UPDATING = 0;
@ -92,10 +95,6 @@ public class UpdateService extends IntentService {
private static boolean updating; private static boolean updating;
public UpdateService() {
super("UpdateService");
}
public static void updateNow(Context context) { public static void updateNow(Context context) {
updateRepoNow(context, null); updateRepoNow(context, null);
} }
@ -106,7 +105,7 @@ public class UpdateService extends IntentService {
if (!TextUtils.isEmpty(address)) { if (!TextUtils.isEmpty(address)) {
intent.setData(Uri.parse(address)); intent.setData(Uri.parse(address));
} }
context.startService(intent); enqueueWork(context, intent);
} }
/** /**
@ -117,7 +116,16 @@ public class UpdateService extends IntentService {
public static void forceUpdateRepo(Context context) { public static void forceUpdateRepo(Context context) {
Intent intent = new Intent(context, UpdateService.class); Intent intent = new Intent(context, UpdateService.class);
intent.putExtra(EXTRA_FORCED_UPDATE, true); intent.putExtra(EXTRA_FORCED_UPDATE, true);
context.startService(intent); enqueueWork(context, intent);
}
/**
* Add work to the queue for processing now
*
* @see JobIntentService#enqueueWork(Context, Class, int, Intent)
*/
private static void enqueueWork(Context context, @NonNull Intent intent) {
enqueueWork(context, UpdateService.class, JOB_ID, intent);
} }
/** /**
@ -150,7 +158,7 @@ public class UpdateService extends IntentService {
Utils.debugLog(TAG, "Using android-21 JobScheduler for updates"); Utils.debugLog(TAG, "Using android-21 JobScheduler for updates");
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
ComponentName componentName = new ComponentName(context, UpdateJobService.class); ComponentName componentName = new ComponentName(context, UpdateJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0xfedcba, componentName) JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName)
.setRequiresDeviceIdle(true) .setRequiresDeviceIdle(true)
.setPeriodic(interval); .setPeriodic(interval);
if (Build.VERSION.SDK_INT >= 26) { if (Build.VERSION.SDK_INT >= 26) {
@ -368,18 +376,13 @@ public class UpdateService extends IntentService {
} }
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(@NonNull Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
final long startTime = System.currentTimeMillis(); final long startTime = System.currentTimeMillis();
boolean manualUpdate = false; boolean manualUpdate = intent.getBooleanExtra(EXTRA_MANUAL_UPDATE, false);
boolean forcedUpdate = false; boolean forcedUpdate = intent.getBooleanExtra(EXTRA_FORCED_UPDATE, false);
String address = null; String address = intent.getDataString();
if (intent != null) {
address = intent.getDataString();
manualUpdate = intent.getBooleanExtra(EXTRA_MANUAL_UPDATE, false);
forcedUpdate = intent.getBooleanExtra(EXTRA_FORCED_UPDATE, false);
}
try { try {
final Preferences fdroidPrefs = Preferences.get(); final Preferences fdroidPrefs = Preferences.get();

View File

@ -47,7 +47,7 @@ import java.util.Locale;
* This also schedules an update to encourage updates happening on * This also schedules an update to encourage updates happening on
* unmetered networks like typical WiFi rather than networks that can * unmetered networks like typical WiFi rather than networks that can
* cost money or have caps. The logic for checking the state of the * cost money or have caps. The logic for checking the state of the
* internet connection is in {@link org.fdroid.fdroid.UpdateService#onHandleIntent(Intent)} * internet connection is in {@link org.fdroid.fdroid.UpdateService#onHandleWork(Intent)}
* <p> * <p>
* Some devices send multiple copies of given events, like a Moto G often * Some devices send multiple copies of given events, like a Moto G often
* sends three {@code CONNECTED} events. So they have to be debounced to * sends three {@code CONNECTED} events. So they have to be debounced to