use JobIntentService for CleanCache, DeleteCache, Installer, InstalledApp

This should ensure that these jobs complete before sleep, and also, they
should work more reliably with the new Android 8.0 background restrictions.
https://developer.android.com/reference/android/support/v4/app/JobIntentService.html #1426
This commit is contained in:
Hans-Christoph Steiner 2018-04-24 16:53:05 +02:00
parent 3785aecc26
commit fe260d931c
5 changed files with 44 additions and 55 deletions

View File

@ -46,6 +46,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Indicate that F-Droid may request root access (introduced by Koush's Superuser app)
This permission is deprecated, but necessary for some old superuser
@ -261,12 +262,15 @@
android:exported="false"/>
<service
android:name=".installer.InstallerService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service
android:name=".CleanCacheService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service
android:name=".DeleteCacheService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service
android:name=".net.WifiStateChangeService"
@ -286,6 +290,7 @@
android:exported="false"/>
<service
android:name=".data.InstalledAppProviderService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<service
android:name=".AppUpdateStatusService"

View File

@ -1,13 +1,14 @@
package org.fdroid.fdroid;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Process;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import org.apache.commons.io.FileUtils;
import org.fdroid.fdroid.installer.ApkCache;
@ -27,7 +28,7 @@ import java.util.concurrent.TimeUnit;
* and newer. On older Android, last modified time from {@link File#lastModified()}
* is used.
*/
public class CleanCacheService extends IntentService {
public class CleanCacheService extends JobIntentService {
/**
* Schedule or cancel this service to update the app index, according to the
@ -35,6 +36,7 @@ public class CleanCacheService extends IntentService {
* is changed, or c) on startup, in case we get upgraded.
*/
public static void schedule(Context context) {
// TODO use JobScheduler
long keepTime = Preferences.get().getKeepCacheTime();
long interval = TimeUnit.DAYS.toMillis(1);
if (keepTime < interval) {
@ -51,18 +53,11 @@ public class CleanCacheService extends IntentService {
}
public static void start(Context context) {
context.startService(new Intent(context, CleanCacheService.class));
}
public CleanCacheService() {
super("CleanCacheService");
enqueueWork(context, CleanCacheService.class, 0x982374, new Intent(context, CleanCacheService.class));
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null) {
return;
}
protected void onHandleWork(@NonNull Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
deleteExpiredApksFromCache();
deleteStrayIndexFiles();

View File

@ -1,9 +1,10 @@
package org.fdroid.fdroid;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Process;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import org.apache.commons.io.FileUtils;
@ -11,25 +12,18 @@ import org.apache.commons.io.FileUtils;
import java.io.File;
/**
* An {@link IntentService} subclass for deleting the full cache for this app.
* An {@link JobIntentService} subclass for deleting the full cache for this app.
*/
public class DeleteCacheService extends IntentService {
public class DeleteCacheService extends JobIntentService {
public static final String TAG = "DeleteCacheService";
public DeleteCacheService() {
super("DeleteCacheService");
}
public static void deleteAll(Context context) {
Intent intent = new Intent(context, DeleteCacheService.class);
context.startService(intent);
enqueueWork(context, DeleteCacheService.class, 0x523432, intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null) {
return;
}
protected void onHandleWork(@NonNull Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
Log.w(TAG, "Deleting all cached contents!");
try {

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.data;
import android.app.IntentService;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@ -8,7 +7,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Process;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.JobIntentService;
import android.util.Log;
import org.acra.ACRA;
import org.fdroid.fdroid.AppUpdateStatusManager;
@ -40,7 +41,7 @@ import java.util.concurrent.TimeUnit;
* of this stuff.
*/
@SuppressWarnings("LineLength")
public class InstalledAppProviderService extends IntentService {
public class InstalledAppProviderService extends JobIntentService {
private static final String TAG = "InstalledAppProviderSer";
private static final String ACTION_INSERT = "org.fdroid.fdroid.data.action.INSERT";
@ -56,10 +57,6 @@ public class InstalledAppProviderService extends IntentService {
*/
private PublishSubject<String> packageChangeNotifier;
public InstalledAppProviderService() {
super("InstalledAppProviderService");
}
@Override
public void onCreate() {
super.onCreate();
@ -121,7 +118,7 @@ public class InstalledAppProviderService extends IntentService {
intent.setAction(ACTION_INSERT);
intent.setData(uri);
intent.putExtra(EXTRA_PACKAGE_INFO, packageInfo);
context.startService(intent);
enqueueWork(context, intent);
}
/**
@ -138,7 +135,11 @@ public class InstalledAppProviderService extends IntentService {
Intent intent = new Intent(context, InstalledAppProviderService.class);
intent.setAction(ACTION_DELETE);
intent.setData(uri);
context.startService(intent);
enqueueWork(context, intent);
}
private static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, InstalledAppProviderService.class, 0x192834, intent);
}
/**
@ -153,7 +154,7 @@ public class InstalledAppProviderService extends IntentService {
* The installed app cache could get out of sync, e.g. if F-Droid crashed/ or
* ran out of battery half way through responding to {@link Intent#ACTION_PACKAGE_ADDED}.
* This method returns immediately, and will continue to work in an
* {@link IntentService}. It doesn't really matter where we put this in the
* {@link JobIntentService}. It doesn't really matter where we put this in the
* bootstrap process, because it runs in its own thread, at the lowest priority:
* {@link Process#THREAD_PRIORITY_LOWEST}.
* <p>
@ -218,11 +219,8 @@ public class InstalledAppProviderService extends IntentService {
}
@Override
protected void onHandleIntent(Intent intent) {
protected void onHandleWork(@NonNull Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
if (intent == null) {
return;
}
String packageName = intent.getData().getSchemeSpecificPart();
final String action = intent.getAction();

View File

@ -20,11 +20,11 @@
package org.fdroid.fdroid.installer;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.fdroid.fdroid.Utils;
@ -37,11 +37,13 @@ import java.io.FileFilter;
* This service handles the install process of apk files and
* uninstall process of apps.
* <p>
* This service is based on an IntentService because:
* - no parallel installs/uninstalls should be allowed,
* i.e., runs sequentially
* - no cancel operation is needed. Cancelling an installation
* would be the same as starting uninstall afterwards
* This service is based on an JobIntentService because:
* <ul>
* <li>no parallel installs/uninstalls should be allowed,
* i.e., runs sequentially</li>
* <li>no cancel operation is needed. Cancelling an installation
* would be the same as starting uninstall afterwards</li>
* </ul>
* <p>
* The download URL is only used as the unique ID that represents this
* particular apk throughout the whole install process in
@ -52,23 +54,15 @@ import java.io.FileFilter;
* <a href="https://developer.android.com/google/play/expansion-files.html">
* APK Expansion Files</a> spec.
*/
public class InstallerService extends IntentService {
public class InstallerService extends JobIntentService {
public static final String TAG = "InstallerService";
private static final String ACTION_INSTALL = "org.fdroid.fdroid.installer.InstallerService.action.INSTALL";
private static final String ACTION_UNINSTALL = "org.fdroid.fdroid.installer.InstallerService.action.UNINSTALL";
public InstallerService() {
super("InstallerService");
}
@Override
protected void onHandleIntent(Intent intent) {
protected void onHandleWork(@NonNull Intent intent) {
final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
if (apk == null) {
Utils.debugLog(TAG, "ignoring intent with null EXTRA_APK: " + intent);
return;
}
Installer installer = InstallerFactory.create(this, apk);
if (ACTION_INSTALL.equals(intent.getAction())) {
@ -117,7 +111,7 @@ public class InstallerService extends IntentService {
intent.setData(localApkUri);
intent.putExtra(Installer.EXTRA_DOWNLOAD_URI, downloadUri);
intent.putExtra(Installer.EXTRA_APK, apk);
context.startService(intent);
enqueueWork(context, intent);
}
/**
@ -130,7 +124,10 @@ public class InstallerService extends IntentService {
Intent intent = new Intent(context, InstallerService.class);
intent.setAction(ACTION_UNINSTALL);
intent.putExtra(Installer.EXTRA_APK, apk);
context.startService(intent);
enqueueWork(context, intent);
}
private static void enqueueWork(Context context, @NonNull Intent intent) {
enqueueWork(context, InstallerService.class, 0x872394, intent);
}
}