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>
</receiver>
<service android:name=".UpdateService"/>
<service
android:name=".UpdateService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service
android:name=".UpdateJobService"
android:exported="false"

View File

@ -3,15 +3,10 @@ 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.
* {@link UpdateService}, which is based on {@link android.support.v4.app.JobIntentService}.
*
* @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 {
@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;
UpdateService.updateNow(this);
return false;
}
@Override
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.Process;
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.content.LocalBroadcastManager;
import android.support.v7.preference.PreferenceManager;
@ -60,7 +62,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class UpdateService extends IntentService {
public class UpdateService extends JobIntentService {
private static final String TAG = "UpdateService";
@ -81,6 +83,7 @@ public class UpdateService extends IntentService {
public static final int STATUS_INFO = 5;
private static final String STATE_LAST_UPDATED = "lastUpdateCheck";
private static final int JOB_ID = 0xfedcba;
private static final int NOTIFY_ID_UPDATING = 0;
@ -92,10 +95,6 @@ public class UpdateService extends IntentService {
private static boolean updating;
public UpdateService() {
super("UpdateService");
}
public static void updateNow(Context context) {
updateRepoNow(context, null);
}
@ -106,7 +105,7 @@ public class UpdateService extends IntentService {
if (!TextUtils.isEmpty(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) {
Intent intent = new Intent(context, UpdateService.class);
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");
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
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)
.setPeriodic(interval);
if (Build.VERSION.SDK_INT >= 26) {
@ -368,18 +376,13 @@ public class UpdateService extends IntentService {
}
@Override
protected void onHandleIntent(Intent intent) {
protected void onHandleWork(@NonNull Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
final long startTime = System.currentTimeMillis();
boolean manualUpdate = false;
boolean forcedUpdate = false;
String address = null;
if (intent != null) {
address = intent.getDataString();
manualUpdate = intent.getBooleanExtra(EXTRA_MANUAL_UPDATE, false);
forcedUpdate = intent.getBooleanExtra(EXTRA_FORCED_UPDATE, false);
}
boolean manualUpdate = intent.getBooleanExtra(EXTRA_MANUAL_UPDATE, false);
boolean forcedUpdate = intent.getBooleanExtra(EXTRA_FORCED_UPDATE, false);
String address = intent.getDataString();
try {
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
* unmetered networks like typical WiFi rather than networks that can
* 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>
* 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