diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index aef660433..84e2e3c7b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -95,6 +95,11 @@
android:name="org.fdroid.fdroid.data.InstalledAppProvider"
android:exported="false"/>
+
+
= app.suggestedVersionCode);
+ .setChecked(app.getPrefs(context).ignoreThisUpdate >= app.suggestedVersionCode);
}
// Ignore on devices without Bluetooth
@@ -880,17 +866,17 @@ public class AppDetails extends AppCompatActivity {
return true;
case IGNOREALL:
- app.ignoreAllUpdates ^= true;
- item.setChecked(app.ignoreAllUpdates);
+ app.getPrefs(this).ignoreAllUpdates ^= true;
+ item.setChecked(app.getPrefs(this).ignoreAllUpdates);
return true;
case IGNORETHIS:
- if (app.ignoreThisUpdate >= app.suggestedVersionCode) {
- app.ignoreThisUpdate = 0;
+ if (app.getPrefs(this).ignoreThisUpdate >= app.suggestedVersionCode) {
+ app.getPrefs(this).ignoreThisUpdate = 0;
} else {
- app.ignoreThisUpdate = app.suggestedVersionCode;
+ app.getPrefs(this).ignoreThisUpdate = app.suggestedVersionCode;
}
- item.setChecked(app.ignoreThisUpdate > 0);
+ item.setChecked(app.getPrefs(this).ignoreThisUpdate > 0);
return true;
case SEND_VIA_BLUETOOTH:
@@ -1600,7 +1586,7 @@ public class AppDetails extends AppCompatActivity {
installed = true;
statusView.setText(getString(R.string.details_installed, app.installedVersionName));
NfcHelper.setAndroidBeam(appDetails, app.packageName);
- if (app.canAndWantToUpdate()) {
+ if (app.canAndWantToUpdate(appDetails)) {
updateWanted = true;
btMain.setText(R.string.menu_upgrade);
} else {
diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java
index 759fbcbde..35f94fd84 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/App.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/App.java
@@ -103,15 +103,7 @@ public class App extends ValueObject implements Comparable, Parcelable {
*/
public String[] requirements;
- /**
- * True if all updates for this app are to be ignored
- */
- public boolean ignoreAllUpdates;
-
- /**
- * True if the current update for this app is to be ignored
- */
- public int ignoreThisUpdate;
+ private AppPrefs prefs;
/**
* To be displayed at 48dp (x1.0)
@@ -233,12 +225,6 @@ public class App extends ValueObject implements Comparable, Parcelable {
case Cols.REQUIREMENTS:
requirements = Utils.parseCommaSeparatedString(cursor.getString(i));
break;
- case Cols.IGNORE_ALLUPDATES:
- ignoreAllUpdates = cursor.getInt(i) == 1;
- break;
- case Cols.IGNORE_THISUPDATE:
- ignoreThisUpdate = cursor.getInt(i);
- break;
case Cols.ICON_URL:
iconUrl = cursor.getString(i);
break;
@@ -471,8 +457,6 @@ public class App extends ValueObject implements Comparable, Parcelable {
values.put(Cols.ANTI_FEATURES, Utils.serializeCommaSeparatedString(antiFeatures));
values.put(Cols.REQUIREMENTS, Utils.serializeCommaSeparatedString(requirements));
values.put(Cols.IS_COMPATIBLE, compatible ? 1 : 0);
- values.put(Cols.IGNORE_ALLUPDATES, ignoreAllUpdates ? 1 : 0);
- values.put(Cols.IGNORE_THISUPDATE, ignoreThisUpdate);
return values;
}
@@ -492,13 +476,21 @@ public class App extends ValueObject implements Comparable, Parcelable {
return updates;
}
+ public AppPrefs getPrefs(Context context) {
+ if (prefs == null) {
+ prefs = AppPrefsProvider.Helper.getPrefsOrDefault(context, this);
+ }
+ return prefs;
+ }
+
/**
* True if there are new versions (apks) available and the user wants
* to be notified about them
*/
- public boolean canAndWantToUpdate() {
+ public boolean canAndWantToUpdate(Context context) {
boolean canUpdate = hasUpdates();
- boolean wantsUpdate = !ignoreAllUpdates && ignoreThisUpdate < suggestedVersionCode;
+ AppPrefs prefs = getPrefs(context);
+ boolean wantsUpdate = !prefs.ignoreAllUpdates && prefs.ignoreThisUpdate < suggestedVersionCode;
return canUpdate && wantsUpdate && !isFiltered();
}
@@ -591,8 +583,6 @@ public class App extends ValueObject implements Comparable, Parcelable {
dest.writeStringArray(this.categories);
dest.writeStringArray(this.antiFeatures);
dest.writeStringArray(this.requirements);
- dest.writeByte(this.ignoreAllUpdates ? (byte) 1 : (byte) 0);
- dest.writeInt(this.ignoreThisUpdate);
dest.writeString(this.iconUrl);
dest.writeString(this.iconUrlLarge);
dest.writeString(this.installedVersionName);
@@ -631,8 +621,6 @@ public class App extends ValueObject implements Comparable, Parcelable {
this.categories = in.createStringArray();
this.antiFeatures = in.createStringArray();
this.requirements = in.createStringArray();
- this.ignoreAllUpdates = in.readByte() != 0;
- this.ignoreThisUpdate = in.readInt();
this.iconUrl = in.readString();
this.iconUrlLarge = in.readString();
this.installedVersionName = in.readString();
diff --git a/app/src/main/java/org/fdroid/fdroid/data/AppPrefs.java b/app/src/main/java/org/fdroid/fdroid/data/AppPrefs.java
new file mode 100644
index 000000000..1f76e1a6e
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/data/AppPrefs.java
@@ -0,0 +1,39 @@
+package org.fdroid.fdroid.data;
+
+public class AppPrefs extends ValueObject {
+
+ /**
+ * True if all updates for this app are to be ignored
+ */
+ public boolean ignoreAllUpdates;
+
+ /**
+ * True if the current update for this app is to be ignored
+ */
+ public int ignoreThisUpdate;
+
+ public AppPrefs(int ignoreThis, boolean ignoreAll) {
+ ignoreThisUpdate = ignoreThis;
+ ignoreAllUpdates = ignoreAll;
+ }
+
+ public static AppPrefs createDefault() {
+ return new AppPrefs(0, false);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o != null && o instanceof AppPrefs &&
+ ((AppPrefs) o).ignoreAllUpdates == ignoreAllUpdates &&
+ ((AppPrefs) o).ignoreThisUpdate == ignoreThisUpdate;
+ }
+
+ @Override
+ public int hashCode() {
+ return (ignoreThisUpdate + "-" + ignoreAllUpdates).hashCode();
+ }
+
+ public AppPrefs createClone() {
+ return new AppPrefs(ignoreThisUpdate, ignoreAllUpdates);
+ }
+}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/AppPrefsProvider.java b/app/src/main/java/org/fdroid/fdroid/data/AppPrefsProvider.java
new file mode 100644
index 000000000..f45f244ff
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/data/AppPrefsProvider.java
@@ -0,0 +1,158 @@
+package org.fdroid.fdroid.data;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import org.fdroid.fdroid.data.Schema.AppPrefsTable;
+import org.fdroid.fdroid.data.Schema.AppPrefsTable.Cols;
+
+public class AppPrefsProvider extends FDroidProvider {
+
+ public static final class Helper {
+ private Helper() { }
+
+ public static void update(Context context, App app, AppPrefs prefs) {
+ ContentValues values = new ContentValues(3);
+ values.put(Cols.IGNORE_ALL_UPDATES, prefs.ignoreAllUpdates);
+ values.put(Cols.IGNORE_THIS_UPDATE, prefs.ignoreThisUpdate);
+
+ if (getPrefsOrNull(context, app) == null) {
+ values.put(Cols.PACKAGE_NAME, app.packageName);
+ context.getContentResolver().insert(getContentUri(), values);
+ } else {
+ context.getContentResolver().update(getAppUri(app.packageName), values, null, null);
+ }
+ }
+
+ @NonNull
+ public static AppPrefs getPrefsOrDefault(Context context, App app) {
+ AppPrefs prefs = getPrefsOrNull(context, app);
+ return prefs == null ? AppPrefs.createDefault() : prefs;
+ }
+
+ @Nullable
+ public static AppPrefs getPrefsOrNull(Context context, App app) {
+ Cursor cursor = context.getContentResolver().query(getAppUri(app.packageName), Cols.ALL, null, null, null);
+ if (cursor == null) {
+ return null;
+ }
+
+ try {
+ if (cursor.getCount() == 0) {
+ return null;
+ }
+
+ cursor.moveToFirst();
+ return new AppPrefs(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Cols.IGNORE_THIS_UPDATE)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Cols.IGNORE_ALL_UPDATES)) > 0);
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ private class Query extends QueryBuilder {
+
+ @Override
+ protected String getRequiredTables() {
+ return AppPrefsTable.NAME;
+ }
+
+ @Override
+ public void addField(String field) {
+ appendField(field, getTableName());
+ }
+ }
+
+ private static final String PROVIDER_NAME = "AppPrefsProvider";
+
+ private static final UriMatcher MATCHER = new UriMatcher(-1);
+
+ private static final String PATH_PACKAGE_NAME = "packageName";
+
+ static {
+ MATCHER.addURI(getAuthority(), PATH_PACKAGE_NAME + "/*", CODE_SINGLE);
+ }
+
+ private static Uri getContentUri() {
+ return Uri.parse("content://" + getAuthority());
+ }
+
+ public static Uri getAppUri(String packageName) {
+ return getContentUri().buildUpon().appendPath(PATH_PACKAGE_NAME).appendPath(packageName).build();
+ }
+
+ @Override
+ protected String getTableName() {
+ return AppPrefsTable.NAME;
+ }
+
+ @Override
+ protected String getProviderName() {
+ return "AppPrefsProvider";
+ }
+
+ public static String getAuthority() {
+ return AUTHORITY + "." + PROVIDER_NAME;
+ }
+
+ @Override
+ protected UriMatcher getMatcher() {
+ return MATCHER;
+ }
+
+ protected QuerySelection querySingle(String packageName) {
+ final String selection = getTableName() + "." + Cols.PACKAGE_NAME + " = ?";
+ final String[] args = {packageName};
+ return new QuerySelection(selection, args);
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String customSelection, String[] selectionArgs, String sortOrder) {
+ if (MATCHER.match(uri) != CODE_SINGLE) {
+ throw new UnsupportedOperationException("Invalid URI for app content provider: " + uri);
+ }
+
+ QuerySelection selection = new QuerySelection(customSelection, selectionArgs)
+ .add(querySingle(uri.getLastPathSegment()));
+
+ Query query = new Query();
+ query.addSelection(selection);
+ query.addFields(projection);
+ query.addOrderBy(sortOrder);
+
+ Cursor cursor = LoggingQuery.query(db(), query.toString(), query.getArgs());
+ cursor.setNotificationUri(getContext().getContentResolver(), uri);
+ return cursor;
+ }
+
+ @Override
+ public int delete(Uri uri, String where, String[] whereArgs) {
+ throw new UnsupportedOperationException("Delete not supported for " + uri + ".");
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ db().insertOrThrow(getTableName(), null, values);
+ getContext().getContentResolver().notifyChange(AppProvider.getCanUpdateUri(), null);
+ return getAppUri(values.getAsString(Cols.PACKAGE_NAME));
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ if (MATCHER.match(uri) != CODE_SINGLE) {
+ throw new UnsupportedOperationException("Update not supported for " + uri + ".");
+ }
+
+ QuerySelection query = new QuerySelection(where, whereArgs).add(querySingle(uri.getLastPathSegment()));
+ int count = db().update(getTableName(), values, query.getSelection(), query.getArgs());
+ getContext().getContentResolver().notifyChange(AppProvider.getCanUpdateUri(), null);
+ return count;
+ }
+}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java b/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java
index 9653ba1c5..4e90d4550 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java
@@ -14,6 +14,7 @@ import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Schema.ApkTable;
+import org.fdroid.fdroid.data.Schema.AppPrefsTable;
import org.fdroid.fdroid.data.Schema.AppTable;
import org.fdroid.fdroid.data.Schema.AppTable.Cols;
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
@@ -58,12 +59,6 @@ public class AppProvider extends FDroidProvider {
return cursorToList(cursor);
}
- public static List findIgnored(Context context, String[] projection) {
- final Uri uri = AppProvider.getIgnoredUri();
- Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
- return cursorToList(cursor);
- }
-
static List cursorToList(Cursor cursor) {
int knownAppCount = cursor != null ? cursor.getCount() : 0;
List apps = new ArrayList<>(knownAppCount);
@@ -153,6 +148,10 @@ public class AppProvider extends FDroidProvider {
final Uri fromUpstream = calcAppDetailsFromIndexUri();
context.getContentResolver().update(fromUpstream, null, null, null);
}
+
+ public static List findCanUpdate(Context context, String[] projection) {
+ return cursorToList(context.getContentResolver().query(AppProvider.getCanUpdateUri(), projection, null, null, null));
+ }
}
/**
@@ -186,6 +185,7 @@ public class AppProvider extends FDroidProvider {
protected static class AppQuerySelection extends QuerySelection {
private boolean naturalJoinToInstalled;
+ private boolean leftJoinPrefs;
AppQuerySelection() {
// The same as no selection, because "1" will always resolve to true when executing the SQL query.
@@ -217,12 +217,25 @@ public class AppProvider extends FDroidProvider {
return this;
}
+ public boolean leftJoinToPrefs() {
+ return leftJoinPrefs;
+ }
+
+ public AppQuerySelection requireLeftJoinPrefs() {
+ leftJoinPrefs = true;
+ return this;
+ }
+
public AppQuerySelection add(AppQuerySelection query) {
QuerySelection both = super.add(query);
AppQuerySelection bothWithJoin = new AppQuerySelection(both.getSelection(), both.getArgs());
if (this.naturalJoinToInstalled() || query.naturalJoinToInstalled()) {
bothWithJoin.requireNaturalInstalledTable();
}
+
+ if (this.leftJoinToPrefs() || query.leftJoinToPrefs()) {
+ bothWithJoin.requireLeftJoinPrefs();
+ }
return bothWithJoin;
}
@@ -232,6 +245,7 @@ public class AppProvider extends FDroidProvider {
private boolean isSuggestedApkTableAdded;
private boolean requiresInstalledTable;
+ private boolean requiresLeftJoinToPrefs;
private boolean categoryFieldAdded;
private boolean countFieldAppended;
@@ -262,6 +276,9 @@ public class AppProvider extends FDroidProvider {
if (selection.naturalJoinToInstalled()) {
naturalJoinToInstalledTable();
}
+ if (selection.leftJoinToPrefs()) {
+ leftJoinToPrefs();
+ }
}
// TODO: What if the selection requires a natural join, but we first get a left join
@@ -276,6 +293,16 @@ public class AppProvider extends FDroidProvider {
}
}
+ public void leftJoinToPrefs() {
+ if (!requiresLeftJoinToPrefs) {
+ leftJoin(
+ AppPrefsTable.NAME,
+ "prefs",
+ "prefs." + AppPrefsTable.Cols.PACKAGE_NAME + " = " + getTableName() + "." + Cols.PACKAGE_NAME);
+ requiresLeftJoinToPrefs = true;
+ }
+ }
+
public void leftJoinToInstalledTable() {
if (!requiresInstalledTable) {
leftJoin(
@@ -377,7 +404,6 @@ public class AppProvider extends FDroidProvider {
private static final String PATH_RECENTLY_UPDATED = "recentlyUpdated";
private static final String PATH_NEWLY_ADDED = "newlyAdded";
private static final String PATH_CATEGORY = "category";
- private static final String PATH_IGNORED = "ignored";
private static final String PATH_CALC_APP_DETAILS_FROM_INDEX = "calcDetailsFromIndex";
private static final String PATH_REPO = "repo";
@@ -388,8 +414,7 @@ public class AppProvider extends FDroidProvider {
private static final int RECENTLY_UPDATED = NO_APKS + 1;
private static final int NEWLY_ADDED = RECENTLY_UPDATED + 1;
private static final int CATEGORY = NEWLY_ADDED + 1;
- private static final int IGNORED = CATEGORY + 1;
- private static final int CALC_APP_DETAILS_FROM_INDEX = IGNORED + 1;
+ private static final int CALC_APP_DETAILS_FROM_INDEX = CATEGORY + 1;
private static final int REPO = CALC_APP_DETAILS_FROM_INDEX + 1;
private static final int SEARCH_REPO = REPO + 1;
private static final int SEARCH_INSTALLED = SEARCH_REPO + 1;
@@ -398,7 +423,6 @@ public class AppProvider extends FDroidProvider {
static {
MATCHER.addURI(getAuthority(), null, CODE_LIST);
MATCHER.addURI(getAuthority(), PATH_CALC_APP_DETAILS_FROM_INDEX, CALC_APP_DETAILS_FROM_INDEX);
- MATCHER.addURI(getAuthority(), PATH_IGNORED, IGNORED);
MATCHER.addURI(getAuthority(), PATH_RECENTLY_UPDATED, RECENTLY_UPDATED);
MATCHER.addURI(getAuthority(), PATH_NEWLY_ADDED, NEWLY_ADDED);
MATCHER.addURI(getAuthority(), PATH_CATEGORY + "/*", CATEGORY);
@@ -425,10 +449,6 @@ public class AppProvider extends FDroidProvider {
return Uri.withAppendedPath(getContentUri(), PATH_NEWLY_ADDED);
}
- public static Uri getIgnoredUri() {
- return Uri.withAppendedPath(getContentUri(), PATH_IGNORED);
- }
-
private static Uri calcAppDetailsFromIndexUri() {
return Uri.withAppendedPath(getContentUri(), PATH_CALC_APP_DETAILS_FROM_INDEX);
}
@@ -527,11 +547,16 @@ public class AppProvider extends FDroidProvider {
private AppQuerySelection queryCanUpdate() {
final String app = getTableName();
- final String ignoreCurrent = app + "." + Cols.IGNORE_THISUPDATE + "!= " + app + "." + Cols.SUGGESTED_VERSION_CODE;
- final String ignoreAll = app + "." + Cols.IGNORE_ALLUPDATES + " != 1";
+
+ // Need to use COALESCE because the prefs join may not resolve any rows, which means the
+ // ignore* fields will be NULL. In that case, we want to instead use a default value of 0.
+ final String ignoreCurrent = " COALESCE(prefs." + AppPrefsTable.Cols.IGNORE_THIS_UPDATE + ", 0) != " + app + "." + Cols.SUGGESTED_VERSION_CODE;
+ final String ignoreAll = "COALESCE(prefs." + AppPrefsTable.Cols.IGNORE_ALL_UPDATES + ", 0) != 1";
+
final String ignore = " (" + ignoreCurrent + " AND " + ignoreAll + ") ";
final String where = ignore + " AND " + app + "." + Cols.SUGGESTED_VERSION_CODE + " > installed." + InstalledAppTable.Cols.VERSION_CODE;
- return new AppQuerySelection(where).requireNaturalInstalledTable();
+
+ return new AppQuerySelection(where).requireNaturalInstalledTable().requireLeftJoinPrefs();
}
private AppQuerySelection queryRepo(long repoId) {
@@ -602,19 +627,12 @@ public class AppProvider extends FDroidProvider {
return new AppQuerySelection(selection, args);
}
- private AppQuerySelection queryIgnored() {
- final String table = getTableName();
- final String selection = table + "." + Cols.IGNORE_ALLUPDATES + " = 1 OR " +
- table + "." + Cols.IGNORE_THISUPDATE + " >= " + table + "." + Cols.SUGGESTED_VERSION_CODE;
- return new AppQuerySelection(selection);
- }
-
private AppQuerySelection queryExcludeSwap() {
// fdroid_repo will have null fields if the LEFT JOIN didn't resolve, e.g. due to there
// being no apks for the app in the result set. In that case, we can't tell if it is from
// a swap repo or not.
final String isSwap = RepoTable.NAME + "." + RepoTable.Cols.IS_SWAP;
- final String selection = isSwap + " = 0 OR " + isSwap + " IS NULL";
+ final String selection = "COALESCE(" + isSwap + ", 0) = 0";
return new AppQuerySelection(selection);
}
@@ -717,10 +735,6 @@ public class AppProvider extends FDroidProvider {
selection = selection.add(queryNoApks());
break;
- case IGNORED:
- selection = selection.add(queryIgnored());
- break;
-
case CATEGORY:
selection = selection.add(queryCategory(uri.getLastPathSegment()));
includeSwap = false;
@@ -896,7 +910,7 @@ public class AppProvider extends FDroidProvider {
" WHERE " +
app + "." + Cols.ROW_ID + " = " + apk + "." + ApkTable.Cols.APP_ID + " AND " +
" ( " + app + "." + Cols.IS_COMPATIBLE + " = 0 OR " + apk + "." + ApkTable.Cols.IS_COMPATIBLE + " = 1 ) ) " +
- " WHERE " + Cols.UPSTREAM_VERSION_CODE + " = 0 OR " + Cols.UPSTREAM_VERSION_CODE + " IS NULL OR " + Cols.SUGGESTED_VERSION_CODE + " IS NULL ";
+ " WHERE COALESCE(" + Cols.UPSTREAM_VERSION_CODE + ", 0) = 0 OR " + Cols.SUGGESTED_VERSION_CODE + " IS NULL ";
db().execSQL(updateSql);
}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java
index c0597b420..2c0fcb24c 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java
@@ -11,6 +11,7 @@ import android.util.Log;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Schema.ApkTable;
+import org.fdroid.fdroid.data.Schema.AppPrefsTable;
import org.fdroid.fdroid.data.Schema.AppTable;
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
import org.fdroid.fdroid.data.Schema.RepoTable;
@@ -95,12 +96,17 @@ class DBHelper extends SQLiteOpenHelper {
+ AppTable.Cols.ADDED + " string,"
+ AppTable.Cols.LAST_UPDATED + " string,"
+ AppTable.Cols.IS_COMPATIBLE + " int not null,"
- + AppTable.Cols.IGNORE_ALLUPDATES + " int not null,"
- + AppTable.Cols.IGNORE_THISUPDATE + " int not null,"
+ AppTable.Cols.ICON_URL + " text, "
+ AppTable.Cols.ICON_URL_LARGE + " text, "
+ "primary key(" + AppTable.Cols.PACKAGE_NAME + "));";
+ private static final String CREATE_TABLE_APP_PREFS = "CREATE TABLE " + AppPrefsTable.NAME
+ + " ( "
+ + AppPrefsTable.Cols.PACKAGE_NAME + " TEXT, "
+ + AppPrefsTable.Cols.IGNORE_THIS_UPDATE + " INT BOOLEAN NOT NULL, "
+ + AppPrefsTable.Cols.IGNORE_ALL_UPDATES + " INT NOT NULL "
+ + " );";
+
private static final String CREATE_TABLE_INSTALLED_APP = "CREATE TABLE " + InstalledAppTable.NAME
+ " ( "
+ InstalledAppTable.Cols.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY, "
@@ -114,7 +120,7 @@ class DBHelper extends SQLiteOpenHelper {
+ " );";
private static final String DROP_TABLE_INSTALLED_APP = "DROP TABLE " + InstalledAppTable.NAME + ";";
- private static final int DB_VERSION = 59;
+ private static final int DB_VERSION = 60;
private final Context context;
@@ -216,9 +222,12 @@ class DBHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
- createAppApk(db);
+ db.execSQL(CREATE_TABLE_APP);
+ db.execSQL(CREATE_TABLE_APK);
db.execSQL(CREATE_TABLE_INSTALLED_APP);
db.execSQL(CREATE_TABLE_REPO);
+ db.execSQL(CREATE_TABLE_APP_PREFS);
+ ensureIndexes(db);
insertRepo(
db,
@@ -296,7 +305,7 @@ class DBHelper extends SQLiteOpenHelper {
// The other tables are transient and can just be reset. Do this after
// the repo table changes though, because it also clears the lastetag
// fields which didn't always exist.
- resetTransient(db, oldVersion);
+ resetTransientPre42(db, oldVersion);
addNameAndDescriptionToRepo(db, oldVersion);
addFingerprintToRepo(db, oldVersion);
@@ -317,6 +326,32 @@ class DBHelper extends SQLiteOpenHelper {
addTargetSdkVersionToApk(db, oldVersion);
migrateAppPrimaryKeyToRowId(db, oldVersion);
removeApkPackageNameColumn(db, oldVersion);
+ addAppPrefsTable(db, oldVersion);
+ }
+
+ private void addAppPrefsTable(SQLiteDatabase db, int oldVersion) {
+ if (oldVersion >= 60) {
+ return;
+ }
+
+ Utils.debugLog(TAG, "Creating app preferences table");
+ db.execSQL(CREATE_TABLE_APP_PREFS);
+
+ Utils.debugLog(TAG, "Migrating app preferences to separate table");
+ db.execSQL(
+ "INSERT INTO " + AppPrefsTable.NAME + " ("
+ + AppPrefsTable.Cols.PACKAGE_NAME + ", "
+ + AppPrefsTable.Cols.IGNORE_THIS_UPDATE + ", "
+ + AppPrefsTable.Cols.IGNORE_ALL_UPDATES
+ + ") SELECT "
+ + AppTable.Cols.PACKAGE_NAME + ", "
+ + "ignoreThisUpdate, "
+ + "ignoreAllUpdates "
+ + "FROM " + AppTable.NAME + " "
+ + "WHERE ignoreThisUpdate > 0 OR ignoreAllUpdates > 0"
+ );
+
+ resetTransient(db);
}
/**
@@ -657,12 +692,27 @@ class DBHelper extends SQLiteOpenHelper {
* their repos (either manually or on a scheduled task), they will update regardless of whether
* they have changed since last update or not.
*/
- private void clearRepoEtags(SQLiteDatabase db) {
+ private static void clearRepoEtags(SQLiteDatabase db) {
Utils.debugLog(TAG, "Clearing repo etags, so next update will not be skipped with \"Repos up to date\".");
db.execSQL("update " + RepoTable.NAME + " set " + RepoTable.Cols.LAST_ETAG + " = NULL");
}
- private void resetTransient(SQLiteDatabase db, int oldVersion) {
+ private void resetTransient(SQLiteDatabase db) {
+ Utils.debugLog(TAG, "Removing app + apk tables so they can be recreated. Next time F-Droid updates it should trigger an index update.");
+ context.getSharedPreferences("FDroid", Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean("triedEmptyUpdate", false)
+ .apply();
+
+ db.execSQL("DROP TABLE " + AppTable.NAME);
+ db.execSQL("DROP TABLE " + ApkTable.NAME);
+ db.execSQL(CREATE_TABLE_APP);
+ db.execSQL(CREATE_TABLE_APK);
+ clearRepoEtags(db);
+ ensureIndexes(db);
+ }
+
+ private void resetTransientPre42(SQLiteDatabase db, int oldVersion) {
// Before version 42, only transient info was stored in here. As of some time
// just before 42 (F-Droid 0.60ish) it now has "ignore this version" info which
// was is specified by the user. We don't want to weely-neely nuke that data.
@@ -672,14 +722,10 @@ class DBHelper extends SQLiteOpenHelper {
return;
}
context.getSharedPreferences("FDroid", Context.MODE_PRIVATE).edit()
- .putBoolean("triedEmptyUpdate", false).commit();
+ .putBoolean("triedEmptyUpdate", false).apply();
db.execSQL("drop table " + AppTable.NAME);
db.execSQL("drop table " + ApkTable.NAME);
clearRepoEtags(db);
- createAppApk(db);
- }
-
- private static void createAppApk(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_APP);
db.execSQL(CREATE_TABLE_APK);
ensureIndexes(db);
@@ -695,6 +741,23 @@ class DBHelper extends SQLiteOpenHelper {
db.execSQL("CREATE INDEX IF NOT EXISTS apk_vercode on " + ApkTable.NAME + " (" + ApkTable.Cols.VERSION_CODE + ");");
db.execSQL("CREATE INDEX IF NOT EXISTS apk_appId on " + ApkTable.NAME + " (" + ApkTable.Cols.APP_ID + ");");
db.execSQL("CREATE INDEX IF NOT EXISTS repoId ON " + ApkTable.NAME + " (" + ApkTable.Cols.REPO_ID + ");");
+
+ if (tableExists(db, AppPrefsTable.NAME)) {
+ Utils.debugLog(TAG, "Ensuring indexes exist for " + AppPrefsTable.NAME);
+ db.execSQL("CREATE INDEX IF NOT EXISTS appPrefs_packageName on " + AppPrefsTable.NAME + " (" + AppPrefsTable.Cols.PACKAGE_NAME + ");");
+ db.execSQL("CREATE INDEX IF NOT EXISTS appPrefs_packageName_ignoreAll_ignoreThis on " + AppPrefsTable.NAME + " (" +
+ AppPrefsTable.Cols.PACKAGE_NAME + ", " +
+ AppPrefsTable.Cols.IGNORE_ALL_UPDATES + ", " +
+ AppPrefsTable.Cols.IGNORE_THIS_UPDATE + ");");
+ }
+
+ Utils.debugLog(TAG, "Ensuring indexes exist for " + InstalledAppTable.NAME);
+ db.execSQL("CREATE INDEX IF NOT EXISTS installedApp_appId_vercode on " + InstalledAppTable.NAME + " (" +
+ InstalledAppTable.Cols.PACKAGE_NAME + ", " + InstalledAppTable.Cols.VERSION_CODE + ");");
+
+ Utils.debugLog(TAG, "Ensuring indexes exist for " + RepoTable.NAME);
+ db.execSQL("CREATE INDEX IF NOT EXISTS repo_id_isSwap on " + RepoTable.NAME + " (" +
+ RepoTable.Cols._ID + ", " + RepoTable.Cols.IS_SWAP + ");");
}
/**
@@ -722,10 +785,14 @@ class DBHelper extends SQLiteOpenHelper {
+ ApkTable.Cols.TARGET_SDK_VERSION + " integer");
}
- private static boolean columnExists(SQLiteDatabase db,
- String table, String column) {
+ private static boolean columnExists(SQLiteDatabase db, String table, String column) {
return db.rawQuery("select * from " + table + " limit 0,1", null)
.getColumnIndex(column) != -1;
}
+ private static boolean tableExists(SQLiteDatabase db, String table) {
+ return db.rawQuery("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?",
+ new String[] {table}).getCount() > 0;
+ }
+
}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java b/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java
index 43e1dd177..fb7df077e 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java
@@ -22,20 +22,6 @@ public class RepoPersister {
private static final String TAG = "RepoPersister";
- /**
- * When an app already exists in the db, and we are updating it on the off chance that some
- * values changed in the index, some fields should not be updated. Rather, they should be
- * ignored, because they were explicitly set by the user, and hence can't be automatically
- * overridden by the index.
- *
- * NOTE: In the future, these attributes will be moved to a join table, so that the app table
- * is essentially completely transient, and can be nuked at any time.
- */
- private static final String[] APP_FIELDS_TO_IGNORE = {
- Schema.AppTable.Cols.IGNORE_ALLUPDATES,
- Schema.AppTable.Cols.IGNORE_THISUPDATE,
- };
-
/**
* Crappy benchmark with a Nexus 4, Android 5.0 on a fairly crappy internet connection I get:
* * 25 = 37 seconds
@@ -219,13 +205,7 @@ public class RepoPersister {
*/
private ContentProviderOperation updateExistingApp(App app) {
Uri uri = TempAppProvider.getAppUri(app);
- ContentValues values = app.toContentValues();
- for (final String toIgnore : APP_FIELDS_TO_IGNORE) {
- if (values.containsKey(toIgnore)) {
- values.remove(toIgnore);
- }
- }
- return ContentProviderOperation.newUpdate(uri).withValues(values).build();
+ return ContentProviderOperation.newUpdate(uri).withValues(app.toContentValues()).build();
}
/**
diff --git a/app/src/main/java/org/fdroid/fdroid/data/Schema.java b/app/src/main/java/org/fdroid/fdroid/data/Schema.java
index 7b39a045a..dfef154c0 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/Schema.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/Schema.java
@@ -9,6 +9,23 @@ import android.provider.BaseColumns;
*/
public interface Schema {
+ interface AppPrefsTable {
+
+ String NAME = "fdroid_appPrefs";
+
+ interface Cols extends BaseColumns {
+ // Join onto app table via packageName, not appId. The corresponding app row could
+ // be deleted and then re-added in the future with the same metadata but a different
+ // rowid. This should not cause us to forget the preferences specified by a user.
+ String PACKAGE_NAME = "packageName";
+
+ String IGNORE_ALL_UPDATES = "ignoreAllUpdates";
+ String IGNORE_THIS_UPDATE = "ignoreThisUpdate";
+
+ String[] ALL = {PACKAGE_NAME, IGNORE_ALL_UPDATES, IGNORE_THIS_UPDATE};
+ }
+ }
+
interface AppTable {
String NAME = "fdroid_app";
@@ -46,8 +63,6 @@ public interface Schema {
String CATEGORIES = "categories";
String ANTI_FEATURES = "antiFeatures";
String REQUIREMENTS = "requirements";
- String IGNORE_ALLUPDATES = "ignoreAllUpdates";
- String IGNORE_THISUPDATE = "ignoreThisUpdate";
String ICON_URL = "iconUrl";
String ICON_URL_LARGE = "iconUrlLarge";
@@ -66,8 +81,7 @@ public interface Schema {
LICENSE, AUTHOR, EMAIL, WEB_URL, TRACKER_URL, SOURCE_URL,
CHANGELOG_URL, DONATE_URL, BITCOIN_ADDR, LITECOIN_ADDR, FLATTR_ID,
UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED,
- CATEGORIES, ANTI_FEATURES, REQUIREMENTS, IGNORE_ALLUPDATES,
- IGNORE_THISUPDATE, ICON_URL, ICON_URL_LARGE,
+ CATEGORIES, ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
SUGGESTED_VERSION_CODE, SuggestedApk.VERSION_NAME,
InstalledApp.VERSION_CODE, InstalledApp.VERSION_NAME,
InstalledApp.SIGNATURE,
diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppListAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppListAdapter.java
index a1f222dc0..17149c6a0 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/AppListAdapter.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/AppListAdapter.java
@@ -123,7 +123,7 @@ public abstract class AppListAdapter extends CursorAdapter {
final String installedVersionString = app.installedVersionName;
- if (app.canAndWantToUpdate() && showStatusUpdate()) {
+ if (app.canAndWantToUpdate(mContext) && showStatusUpdate()) {
return String.format(upgradeFromTo,
installedVersionString, app.getSuggestedVersionName());
}
diff --git a/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java b/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
index 1886af329..67e267288 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
@@ -50,8 +50,6 @@ public abstract class AppListFragment extends ListFragment implements
AppTable.Cols.InstalledApp.VERSION_NAME,
AppTable.Cols.SuggestedApk.VERSION_NAME,
AppTable.Cols.SUGGESTED_VERSION_CODE,
- AppTable.Cols.IGNORE_ALLUPDATES,
- AppTable.Cols.IGNORE_THISUPDATE,
AppTable.Cols.REQUIREMENTS, // Needed for filtering apps that require root.
};
diff --git a/app/src/test/java/org/fdroid/fdroid/Assert.java b/app/src/test/java/org/fdroid/fdroid/Assert.java
index 40b59e71e..459a8f9ba 100644
--- a/app/src/test/java/org/fdroid/fdroid/Assert.java
+++ b/app/src/test/java/org/fdroid/fdroid/Assert.java
@@ -191,8 +191,6 @@ public class Assert {
values.put(AppTable.Cols.DESCRIPTION, "test description");
values.put(AppTable.Cols.LICENSE, "GPL?");
values.put(AppTable.Cols.IS_COMPATIBLE, 1);
- values.put(AppTable.Cols.IGNORE_ALLUPDATES, 0);
- values.put(AppTable.Cols.IGNORE_THISUPDATE, 0);
values.putAll(additionalValues);
diff --git a/app/src/test/java/org/fdroid/fdroid/data/AppPrefsProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/AppPrefsProviderTest.java
new file mode 100644
index 000000000..150e99f99
--- /dev/null
+++ b/app/src/test/java/org/fdroid/fdroid/data/AppPrefsProviderTest.java
@@ -0,0 +1,68 @@
+package org.fdroid.fdroid.data;
+
+import android.app.Application;
+
+import org.fdroid.fdroid.Assert;
+import org.fdroid.fdroid.BuildConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowContentResolver;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+// TODO: Use sdk=24 when Robolectric supports this
+@Config(constants = BuildConfig.class, application = Application.class, sdk = 23)
+@RunWith(RobolectricGradleTestRunner.class)
+public class AppPrefsProviderTest extends FDroidProviderTest {
+
+ @Before
+ public void setup() {
+ ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
+ }
+
+ @SuppressWarnings({"PMD.EqualsNull", "EqualsWithItself", "EqualsBetweenInconvertibleTypes", "ObjectEqualsNull"})
+ @Test
+ public void prefEquality() {
+ AppPrefs original = new AppPrefs(101, true);
+
+ assertTrue(original.equals(new AppPrefs(101, true)));
+ assertTrue(original.equals(original));
+
+ assertFalse(original.equals(null));
+ assertFalse(original.equals("String"));
+ assertFalse(original.equals(new AppPrefs(102, true)));
+ assertFalse(original.equals(new AppPrefs(101, false)));
+ assertFalse(original.equals(new AppPrefs(100, false)));
+ }
+
+ @Test
+ public void newPreferences() {
+ App withPrefs = Assert.insertApp(context, "com.example.withPrefs", "With Prefs");
+ App withoutPrefs = Assert.insertApp(context, "com.example.withoutPrefs", "Without Prefs");
+
+ assertNull(AppPrefsProvider.Helper.getPrefsOrNull(context, withPrefs));
+ assertNull(AppPrefsProvider.Helper.getPrefsOrNull(context, withoutPrefs));
+
+ AppPrefs defaultPrefs = AppPrefsProvider.Helper.getPrefsOrDefault(context, withPrefs);
+ assertEquals(0, defaultPrefs.ignoreThisUpdate);
+ assertFalse(defaultPrefs.ignoreAllUpdates);
+
+ AppPrefsProvider.Helper.update(context, withPrefs, new AppPrefs(12, false));
+ AppPrefs newPrefs = AppPrefsProvider.Helper.getPrefsOrDefault(context, withPrefs);
+ assertEquals(12, newPrefs.ignoreThisUpdate);
+ assertFalse(newPrefs.ignoreAllUpdates);
+
+ AppPrefsProvider.Helper.update(context, withPrefs, new AppPrefs(14, true));
+ AppPrefs evenNewerPrefs = AppPrefsProvider.Helper.getPrefsOrDefault(context, withPrefs);
+ assertEquals(14, evenNewerPrefs.ignoreThisUpdate);
+ assertTrue(evenNewerPrefs.ignoreAllUpdates);
+
+ assertNull(AppPrefsProvider.Helper.getPrefsOrNull(context, withoutPrefs));
+ }
+}
diff --git a/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
index 170710365..f4cb5e01b 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
@@ -89,9 +89,8 @@ public class AppProviderTest extends FDroidProviderTest {
boolean ignoreAll, int ignoreVercode) {
ContentValues values = new ContentValues(3);
values.put(Cols.SUGGESTED_VERSION_CODE, suggestedVercode);
- values.put(Cols.IGNORE_ALLUPDATES, ignoreAll);
- values.put(Cols.IGNORE_THISUPDATE, ignoreVercode);
- insertApp(packageName, "App: " + packageName, values);
+ App app = insertApp(packageName, "App: " + packageName, values);
+ AppPrefsProvider.Helper.update(context, app, new AppPrefs(ignoreVercode, ignoreAll));
InstalledAppTestUtils.install(context, packageName, installedVercode, "v" + installedVercode);
}
@@ -113,7 +112,7 @@ public class AppProviderTest extends FDroidProviderTest {
// Can't "update", although can "install"...
App notInstalled = AppProvider.Helper.findByPackageName(r, "not installed");
- assertFalse(notInstalled.canAndWantToUpdate());
+ assertFalse(notInstalled.canAndWantToUpdate(context));
App installedOnlyOneVersionAvailable = AppProvider.Helper.findByPackageName(r, "installed, only one version available");
App installedAlreadyLatestNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, already latest, no ignore");
@@ -121,21 +120,21 @@ public class AppProviderTest extends FDroidProviderTest {
App installedAlreadyLatestIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore latest");
App installedAlreadyLatestIgnoreOld = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore old");
- assertFalse(installedOnlyOneVersionAvailable.canAndWantToUpdate());
- assertFalse(installedAlreadyLatestNoIgnore.canAndWantToUpdate());
- assertFalse(installedAlreadyLatestIgnoreAll.canAndWantToUpdate());
- assertFalse(installedAlreadyLatestIgnoreLatest.canAndWantToUpdate());
- assertFalse(installedAlreadyLatestIgnoreOld.canAndWantToUpdate());
+ assertFalse(installedOnlyOneVersionAvailable.canAndWantToUpdate(context));
+ assertFalse(installedAlreadyLatestNoIgnore.canAndWantToUpdate(context));
+ assertFalse(installedAlreadyLatestIgnoreAll.canAndWantToUpdate(context));
+ assertFalse(installedAlreadyLatestIgnoreLatest.canAndWantToUpdate(context));
+ assertFalse(installedAlreadyLatestIgnoreOld.canAndWantToUpdate(context));
App installedOldNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, old version, no ignore");
App installedOldIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore all");
App installedOldIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore latest");
App installedOldIgnoreNewerNotLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore newer, but not latest");
- assertTrue(installedOldNoIgnore.canAndWantToUpdate());
- assertFalse(installedOldIgnoreAll.canAndWantToUpdate());
- assertFalse(installedOldIgnoreLatest.canAndWantToUpdate());
- assertTrue(installedOldIgnoreNewerNotLatest.canAndWantToUpdate());
+ assertTrue(installedOldNoIgnore.canAndWantToUpdate(context));
+ assertFalse(installedOldIgnoreAll.canAndWantToUpdate(context));
+ assertFalse(installedOldIgnoreLatest.canAndWantToUpdate(context));
+ assertTrue(installedOldIgnoreNewerNotLatest.canAndWantToUpdate(context));
Cursor canUpdateCursor = r.query(AppProvider.getCanUpdateUri(), Cols.ALL, null, null, null);
assertNotNull(canUpdateCursor);
@@ -171,21 +170,27 @@ public class AppProviderTest extends FDroidProviderTest {
assertResultCount(contentResolver, 10, AppProvider.getContentUri(), PROJ);
String[] projection = {Cols.PACKAGE_NAME};
- List ignoredApps = AppProvider.Helper.findIgnored(context, projection);
+ List canUpdateApps = AppProvider.Helper.findCanUpdate(context, projection);
- String[] expectedIgnored = {
- "installed, already latest, ignore all",
- "installed, already latest, ignore latest",
- // NOT "installed, already latest, ignore old" - because it
- // is should only ignore if "ignored version" is >= suggested
+ String[] expectedCanUpdate = {
+ "installed, old version, no ignore",
+ "installed, old version, ignore newer, but not latest",
+
+ // These are ignored because they don't have updates available:
+ // "installed, only one version available",
+ // "installed, already latest, no ignore",
+ // "installed, already latest, ignore old",
+ // "not installed",
+
+ // These four should be ignored due to the app preferences:
+ // "installed, already latest, ignore all",
+ // "installed, already latest, ignore latest",
+ // "installed, old version, ignore all",
+ // "installed, old version, ignore latest",
- "installed, old version, ignore all",
- "installed, old version, ignore latest",
- // NOT "installed, old version, ignore newer, but not latest"
- // for the same reason as above.
};
- assertContainsOnlyIds(ignoredApps, expectedIgnored);
+ assertContainsOnlyIds(canUpdateApps, expectedCanUpdate);
}
private void assertContainsOnlyIds(List actualApps, String[] expectedIds) {
@@ -348,7 +353,7 @@ public class AppProviderTest extends FDroidProviderTest {
insertApp(id, name, values);
}
- public void insertApp(String id, String name, ContentValues additionalValues) {
+ public App insertApp(String id, String name, ContentValues additionalValues) {
ContentValues values = new ContentValues();
values.put(Cols.PACKAGE_NAME, id);
@@ -359,13 +364,12 @@ public class AppProviderTest extends FDroidProviderTest {
values.put(Cols.DESCRIPTION, "test description");
values.put(Cols.LICENSE, "GPL?");
values.put(Cols.IS_COMPATIBLE, 1);
- values.put(Cols.IGNORE_ALLUPDATES, 0);
- values.put(Cols.IGNORE_THISUPDATE, 0);
values.putAll(additionalValues);
Uri uri = AppProvider.getContentUri();
contentResolver.insert(uri, values);
+ return AppProvider.Helper.findByPackageName(context.getContentResolver(), id);
}
}