diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index c7b46187d..405793f48 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -313,11 +313,14 @@ public class UpdateService extends IntentService implements ProgressListener { calcIconUrls(this, apksToUpdate, appsToUpdate, repos); calcCurrentApk(apksToUpdate, appsToUpdate); + // Need to do this BEFORE updating the apks, otherwise when it continually + // calls "get apks for repo X" then it will be getting the newly created apks + removeApksNoLongerInRepo(apksToUpdate, updatedRepos); + int totalInsertsUpdates = listOfAppsToUpdate.size() + apksToUpdate.size(); updateOrInsertApps(listOfAppsToUpdate, totalInsertsUpdates, 0); updateOrInsertApks(apksToUpdate, totalInsertsUpdates, listOfAppsToUpdate.size()); removeApksFromRepos(disabledRepos); - removeApksNoLongerInRepo(listOfAppsToUpdate, updatedRepos); removeAppsWithoutApks(); notifyContentProviders(); @@ -618,7 +621,7 @@ public class UpdateService extends IntentService implements ProgressListener { } /** - * Return list of apps from "fromApks" which are already in the database. + * Return list of apps from the "apks" argument which are already in the database. */ private List getKnownApks(List apks) { List knownApks = new ArrayList(); @@ -701,26 +704,54 @@ public class UpdateService extends IntentService implements ProgressListener { * belong to the repo which are not in the current list of apks that were * retrieved. */ - private void removeApksNoLongerInRepo(List appsToUpdate, - List updatedRepos) { + private void removeApksNoLongerInRepo(List apksToUpdate, List updatedRepos) { + + long startTime = System.currentTimeMillis(); + List toRemove = new ArrayList(); + + String[] fields = { + ApkProvider.DataColumns.APK_ID, + ApkProvider.DataColumns.VERSION_CODE, + ApkProvider.DataColumns.VERSION, + }; + for (Repo repo : updatedRepos) { - Log.d("FDroid", "Removing apks no longer in repo " + repo.address); - // TODO: Implement + List existingApks = ApkProvider.Helper.findByRepo(this, repo, fields); + for (Apk existingApk : existingApks) { + if (!isApkToBeUpdated(existingApk, apksToUpdate)) { + toRemove.add(existingApk); + } + } } + long duration = System.currentTimeMillis() - startTime; + Log.d("FDroid", "Found " + toRemove.size() + " apks no longer in the updated repos (took " + duration + "ms)"); + + if (toRemove.size() > 0) { + ApkProvider.Helper.deleteApks(this, toRemove); + } + } + + private static boolean isApkToBeUpdated(Apk existingApk, List apksToUpdate) { + for (Apk apkToUpdate : apksToUpdate) { + if (apkToUpdate.vercode == existingApk.vercode && apkToUpdate.id.equals(existingApk.id)) { + return true; + } + } + return false; } private void removeApksFromRepos(List repos) { for (Repo repo : repos) { - Log.d("FDroid", "Removing apks from repo " + repo.address); Uri uri = ApkProvider.getRepoUri(repo.getId()); - getContentResolver().delete(uri, null, null); + int numDeleted = getContentResolver().delete(uri, null, null); + Log.d("FDroid", "Removing " + numDeleted + " apks from repo " + repo.address); } } private void removeAppsWithoutApks() { - Log.d("FDroid", "Removing aps that don't have any apks"); - getContentResolver().delete(AppProvider.getNoApksUri(), null, null); + int numDeleted = getContentResolver().delete(AppProvider.getNoApksUri(), null, null); + Log.d("FDroid", "Removing " + numDeleted + " apks that don't have any apks"); } diff --git a/src/org/fdroid/fdroid/data/ApkProvider.java b/src/org/fdroid/fdroid/data/ApkProvider.java index 9ecff515a..942af616b 100644 --- a/src/org/fdroid/fdroid/data/ApkProvider.java +++ b/src/org/fdroid/fdroid/data/ApkProvider.java @@ -8,6 +8,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.BaseColumns; import android.util.Log; +import org.fdroid.fdroid.UpdateService; import java.util.*; @@ -59,6 +60,12 @@ public class ApkProvider extends FDroidProvider { resolver.delete(uri, null, null); } + public static void deleteApks(Context context, List apks) { + ContentResolver resolver = context.getContentResolver(); + Uri uri = getContentUri(apks); + resolver.delete(uri, null, null); + } + public static Apk find(Context context, String id, int versionCode) { return find(context, id, versionCode, DataColumns.ALL); } @@ -102,6 +109,13 @@ public class ApkProvider extends FDroidProvider { Cursor cursor = resolver.query(uri, fields, null, null, null); return cursorToList(cursor); } + + public static List findByRepo(Context context, Repo repo, String[] fields) { + ContentResolver resolver = context.getContentResolver(); + Uri uri = getRepoUri(repo.getId()); + Cursor cursor = resolver.query(uri, fields, null, null, null); + return cursorToList(cursor); + } } public interface DataColumns extends BaseColumns { @@ -392,20 +406,15 @@ public class ApkProvider extends FDroidProvider { query = query.add(queryApp(uri.getLastPathSegment())); break; - case CODE_LIST: - throw new UnsupportedOperationException( - "Can't delete all apks. " + - "Can only delete those belonging to an app, or a repo."); - case CODE_APKS: - throw new UnsupportedOperationException( - "Can't delete arbitrary apks. " + - "Can only delete those belonging to an app, or a repo."); + query = query.add(queryApks(uri.getLastPathSegment())); + break; + + case CODE_LIST: + throw new UnsupportedOperationException("Can't delete all apks."); case CODE_SINGLE: - throw new UnsupportedOperationException( - "Can't delete individual apks. " + - "Can only delete those belonging to an app, or a repo."); + throw new UnsupportedOperationException("Can't delete individual apks."); default: Log.e("FDroid", "Invalid URI for apk content provider: " + uri);