diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 70cecf9cb..eb2332ace 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -100,6 +100,11 @@
android:name="org.fdroid.fdroid.data.AppPrefsProvider"
android:exported="false"/>
+
+
, Parcelable {
public String[] incompatibleReasons;
/**
- * The numeric primary key of the App table, which is used to join apks.
+ * The numeric primary key of the Package table, which is used to join apks.
*/
public long appId;
@@ -91,7 +91,7 @@ public class Apk extends ValueObject implements Comparable, Parcelable {
case Cols.FEATURES:
features = Utils.parseCommaSeparatedString(cursor.getString(i));
break;
- case Cols.App.PACKAGE_NAME:
+ case Cols.Package.PACKAGE_NAME:
packageName = cursor.getString(i);
break;
case Cols.IS_COMPATIBLE:
diff --git a/app/src/main/java/org/fdroid/fdroid/data/ApkProvider.java b/app/src/main/java/org/fdroid/fdroid/data/ApkProvider.java
index 3c635c35f..e79380132 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/ApkProvider.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/ApkProvider.java
@@ -11,6 +11,7 @@ import android.util.Log;
import org.fdroid.fdroid.data.Schema.ApkTable;
import org.fdroid.fdroid.data.Schema.ApkTable.Cols;
import org.fdroid.fdroid.data.Schema.AppMetadataTable;
+import org.fdroid.fdroid.data.Schema.PackageTable;
import org.fdroid.fdroid.data.Schema.RepoTable;
import java.util.ArrayList;
@@ -189,7 +190,7 @@ public class ApkProvider extends FDroidProvider {
static {
REPO_FIELDS.put(Cols.Repo.VERSION, RepoTable.Cols.VERSION);
REPO_FIELDS.put(Cols.Repo.ADDRESS, RepoTable.Cols.ADDRESS);
- PACKAGE_FIELDS.put(Cols.App.PACKAGE_NAME, AppMetadataTable.Cols.PACKAGE_NAME);
+ PACKAGE_FIELDS.put(Cols.Package.PACKAGE_NAME, PackageTable.Cols.PACKAGE_NAME);
MATCHER.addURI(getAuthority(), PATH_REPO + "/#", CODE_REPO);
MATCHER.addURI(getAuthority(), PATH_APK + "/#/*", CODE_SINGLE);
@@ -317,9 +318,11 @@ public class ApkProvider extends FDroidProvider {
protected String getRequiredTables() {
final String apk = getTableName();
final String app = getAppTableName();
+ final String pkg = PackageTable.NAME;
return apk + " AS apk " +
- " LEFT JOIN " + app + " AS app ON (app." + AppMetadataTable.Cols.ROW_ID + " = apk." + Cols.APP_ID + ")";
+ " LEFT JOIN " + app + " AS app ON (app." + AppMetadataTable.Cols.ROW_ID + " = apk." + Cols.APP_ID + ")" +
+ " LEFT JOIN " + pkg + " AS pkg ON (pkg." + PackageTable.Cols.ROW_ID + " = app." + AppMetadataTable.Cols.PACKAGE_ID + ")";
}
@Override
@@ -340,7 +343,7 @@ public class ApkProvider extends FDroidProvider {
}
private void addPackageField(String field, String alias) {
- appendField(field, "app", alias);
+ appendField(field, "pkg", alias);
}
private void addRepoField(String field, String alias) {
@@ -354,12 +357,7 @@ public class ApkProvider extends FDroidProvider {
}
private QuerySelection queryPackage(String packageName) {
- return queryPackage(packageName, true);
- }
-
- private QuerySelection queryPackage(String packageName, boolean includeTableAlias) {
- String alias = includeTableAlias ? "apk." : "";
- final String selection = alias + Cols.APP_ID + " = (" + getAppIdFromPackageNameQuery() + ")";
+ final String selection = "pkg." + PackageTable.Cols.PACKAGE_NAME + " = ?";
final String[] args = {packageName};
return new QuerySelection(selection, args);
}
@@ -370,7 +368,9 @@ public class ApkProvider extends FDroidProvider {
private QuerySelection querySingleFromAnyRepo(Uri uri, boolean includeAlias) {
String alias = includeAlias ? "apk." : "";
- final String selection = alias + Cols.VERSION_CODE + " = ? and " + alias + Cols.APP_ID + " = (" + getAppIdFromPackageNameQuery() + ")";
+
+ // TODO: Change the = to an IN to deal with multiple apps?
+ final String selection = alias + Cols.VERSION_CODE + " = ? and " + alias + Cols.APP_ID + " = (" + getMetadataIdFromPackageNameQuery() + ")";
final String[] args = {
// First (0th) path segment is the word "apk",
// and we are not interested in it.
@@ -403,7 +403,7 @@ public class ApkProvider extends FDroidProvider {
}
private QuerySelection queryRepoApps(long repoId, String packageNames) {
- return queryRepo(repoId).add(AppProvider.queryPackageNames(packageNames, "app." + AppMetadataTable.Cols.PACKAGE_NAME));
+ return queryRepo(repoId).add(AppProvider.queryPackageNames(packageNames, "pkg." + PackageTable.Cols.PACKAGE_NAME));
}
protected QuerySelection queryApks(String apkKeys) {
@@ -418,6 +418,7 @@ public class ApkProvider extends FDroidProvider {
"You tried to query " + apkDetails.length);
}
String alias = includeAlias ? "apk." : "";
+ String metadataAlias = includeAlias ? "app." : "";
final String[] args = new String[apkDetails.length * 2];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < apkDetails.length; i++) {
@@ -430,10 +431,10 @@ public class ApkProvider extends FDroidProvider {
sb.append(" OR ");
}
sb.append(" ( ")
- .append(alias)
- .append(Cols.APP_ID)
+ .append(metadataAlias)
+ .append(AppMetadataTable.Cols.PACKAGE_ID)
.append(" = (")
- .append(getAppIdFromPackageNameQuery())
+ .append(getPackageIdFromPackageNameQuery())
.append(") AND ")
.append(alias)
.append(Cols.VERSION_CODE)
@@ -442,8 +443,13 @@ public class ApkProvider extends FDroidProvider {
return new QuerySelection(sb.toString(), args);
}
- private String getAppIdFromPackageNameQuery() {
- return "SELECT " + AppMetadataTable.Cols.ROW_ID + " FROM " + getAppTableName() + " WHERE " + AppMetadataTable.Cols.PACKAGE_NAME + " = ?";
+ // TODO: This could return many rows of app metadata
+ private String getMetadataIdFromPackageNameQuery() {
+ return "SELECT app." + AppMetadataTable.Cols.ROW_ID + " " +
+ "FROM " + AppMetadataTable.NAME + " AS app " +
+ "JOIN " + PackageTable.NAME + " AS pkg ON ( " +
+ " app." + AppMetadataTable.Cols.PACKAGE_ID + " = pkg." + PackageTable.Cols.ROW_ID + " ) " +
+ "WHERE pkg." + PackageTable.Cols.PACKAGE_NAME + " = ?";
}
@Override
@@ -535,10 +541,6 @@ public class ApkProvider extends FDroidProvider {
query = query.add(queryRepo(Long.parseLong(uri.getLastPathSegment()), false));
break;
- case CODE_PACKAGE:
- query = query.add(queryPackage(uri.getLastPathSegment(), false));
- break;
-
case CODE_APKS:
query = query.add(queryApks(uri.getLastPathSegment(), false));
break;
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 cfd6c7c74..1f5c257e8 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/App.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/App.java
@@ -46,6 +46,7 @@ public class App extends ValueObject implements Comparable, Parcelable {
public String packageName = "unknown";
public String name = "Unknown";
+ public long repoId;
public String summary = "Unknown application";
public String icon;
@@ -147,10 +148,13 @@ public class App extends ValueObject implements Comparable, Parcelable {
case Cols.ROW_ID:
id = cursor.getLong(i);
break;
+ case Cols.REPO_ID:
+ repoId = cursor.getLong(i);
+ break;
case Cols.IS_COMPATIBLE:
compatible = cursor.getInt(i) == 1;
break;
- case Cols.PACKAGE_NAME:
+ case Cols.Package.PACKAGE_NAME:
packageName = cursor.getString(i);
break;
case Cols.NAME:
@@ -430,8 +434,9 @@ public class App extends ValueObject implements Comparable, Parcelable {
final ContentValues values = new ContentValues();
// Intentionally don't put "ROW_ID" in here, because we don't ever want to change that
// primary key generated by sqlite.
- values.put(Cols.PACKAGE_NAME, packageName);
+ values.put(Cols.Package.PACKAGE_NAME, packageName);
values.put(Cols.NAME, name);
+ values.put(Cols.REPO_ID, repoId);
values.put(Cols.SUMMARY, summary);
values.put(Cols.ICON, icon);
values.put(Cols.ICON_URL, iconUrl);
@@ -560,6 +565,7 @@ public class App extends ValueObject implements Comparable, Parcelable {
dest.writeByte(this.compatible ? (byte) 1 : (byte) 0);
dest.writeString(this.packageName);
dest.writeString(this.name);
+ dest.writeLong(this.repoId);
dest.writeString(this.summary);
dest.writeString(this.icon);
dest.writeString(this.description);
@@ -596,6 +602,7 @@ public class App extends ValueObject implements Comparable, Parcelable {
this.compatible = in.readByte() != 0;
this.packageName = in.readString();
this.name = in.readString();
+ this.repoId = in.readLong();
this.summary = in.readString();
this.icon = in.readString();
this.description = in.readString();
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 256884f35..3d4bbe282 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java
@@ -18,6 +18,7 @@ import org.fdroid.fdroid.data.Schema.AppPrefsTable;
import org.fdroid.fdroid.data.Schema.AppMetadataTable;
import org.fdroid.fdroid.data.Schema.AppMetadataTable.Cols;
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
+import org.fdroid.fdroid.data.Schema.PackageTable;
import org.fdroid.fdroid.data.Schema.RepoTable;
import java.util.ArrayList;
@@ -120,13 +121,17 @@ public class AppProvider extends FDroidProvider {
return categories;
}
- public static App findByPackageName(ContentResolver resolver, String packageName) {
- return findByPackageName(resolver, packageName, Cols.ALL);
+ public static App findHighestPriorityMetadata(ContentResolver resolver, String packageName) {
+ throw new UnsupportedOperationException("TODO: Pull back the metadata with the highest priority for packageName");
}
- public static App findByPackageName(ContentResolver resolver, String packageName,
+ public static App findByPackageName(ContentResolver resolver, String packageName, long repoId) {
+ return findByPackageName(resolver, packageName, repoId, Cols.ALL);
+ }
+
+ public static App findByPackageName(ContentResolver resolver, String packageName, long repoId,
String[] projection) {
- final Uri uri = getContentUri(packageName);
+ final Uri uri = getAppUri(packageName, repoId);
return cursorToApp(resolver.query(uri, projection, null, null, null));
}
@@ -254,11 +259,13 @@ public class AppProvider extends FDroidProvider {
@Override
protected String getRequiredTables() {
+ final String pkg = PackageTable.NAME;
final String app = getTableName();
final String apk = getApkTableName();
final String repo = RepoTable.NAME;
- return app +
+ return pkg +
+ " JOIN " + app + " ON (" + app + "." + Cols.PACKAGE_ID + " = " + pkg + "." + PackageTable.Cols.ROW_ID + ") " +
" LEFT JOIN " + apk + " ON (" + apk + "." + ApkTable.Cols.APP_ID + " = " + app + "." + Cols.ROW_ID + ") " +
" LEFT JOIN " + repo + " ON (" + apk + "." + ApkTable.Cols.REPO_ID + " = " + repo + "." + RepoTable.Cols._ID + ") ";
}
@@ -291,7 +298,7 @@ public class AppProvider extends FDroidProvider {
join(
InstalledAppTable.NAME,
"installed",
- "installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + getTableName() + "." + Cols.PACKAGE_NAME);
+ "installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
requiresInstalledTable = true;
}
}
@@ -301,7 +308,7 @@ public class AppProvider extends FDroidProvider {
leftJoin(
AppPrefsTable.NAME,
"prefs",
- "prefs." + AppPrefsTable.Cols.PACKAGE_NAME + " = " + getTableName() + "." + Cols.PACKAGE_NAME);
+ "prefs." + AppPrefsTable.Cols.PACKAGE_NAME + " = " + PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
requiresLeftJoinToPrefs = true;
}
}
@@ -311,7 +318,7 @@ public class AppProvider extends FDroidProvider {
leftJoin(
InstalledAppTable.NAME,
"installed",
- "installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + getTableName() + "." + Cols.PACKAGE_NAME);
+ "installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
requiresInstalledTable = true;
}
}
@@ -319,6 +326,9 @@ public class AppProvider extends FDroidProvider {
@Override
public void addField(String field) {
switch (field) {
+ case Cols.Package.PACKAGE_NAME:
+ appendField(PackageTable.Cols.PACKAGE_NAME, PackageTable.NAME, Cols.Package.PACKAGE_NAME);
+ break;
case Cols.SuggestedApk.VERSION_NAME:
addSuggestedApkVersionField();
break;
@@ -404,6 +414,7 @@ public class AppProvider extends FDroidProvider {
private static final String PATH_SEARCH_REPO = "searchRepo";
private static final String PATH_NO_APKS = "noApks";
protected static final String PATH_APPS = "apps";
+ protected static final String PATH_APP = "app";
private static final String PATH_RECENTLY_UPDATED = "recentlyUpdated";
private static final String PATH_NEWLY_ADDED = "newlyAdded";
private static final String PATH_CATEGORY = "category";
@@ -437,7 +448,7 @@ public class AppProvider extends FDroidProvider {
MATCHER.addURI(getAuthority(), PATH_CAN_UPDATE, CAN_UPDATE);
MATCHER.addURI(getAuthority(), PATH_INSTALLED, INSTALLED);
MATCHER.addURI(getAuthority(), PATH_NO_APKS, NO_APKS);
- MATCHER.addURI(getAuthority(), "*", CODE_SINGLE);
+ MATCHER.addURI(getAuthority(), PATH_APP + "/#/*", CODE_SINGLE);
}
public static Uri getContentUri() {
@@ -486,6 +497,19 @@ public class AppProvider extends FDroidProvider {
return getContentUri(app.packageName);
}
+ public static Uri getAppUri(App app) {
+ return getAppUri(app.packageName, app.repoId);
+ }
+
+ public static Uri getAppUri(String packageName, long repoId) {
+ return getContentUri()
+ .buildUpon()
+ .appendPath(PATH_APP)
+ .appendPath(Long.toString(repoId))
+ .appendPath(packageName)
+ .build();
+ }
+
public static Uri getContentUri(String packageName) {
return Uri.withAppendedPath(getContentUri(), packageName);
}
@@ -590,7 +614,7 @@ public class AppProvider extends FDroidProvider {
final String app = getTableName();
final String[] columns = {
- app + "." + Cols.PACKAGE_NAME,
+ PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME,
app + "." + Cols.NAME,
app + "." + Cols.SUMMARY,
app + "." + Cols.DESCRIPTION,
@@ -624,12 +648,25 @@ public class AppProvider extends FDroidProvider {
return new AppQuerySelection(selection.toString(), selectionKeywords);
}
- protected AppQuerySelection querySingle(String packageName) {
- final String selection = getTableName() + "." + Cols.PACKAGE_NAME + " = ?";
+ protected AppQuerySelection querySingle(String packageName, long repoId) {
+ final String selection = PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME + " = ?";
final String[] args = {packageName};
return new AppQuerySelection(selection, args);
}
+ /**
+ * Same as {@link AppProvider#querySingle(String, long)} except it is used for the purpose
+ * of an UPDATE query rather than a SELECT query. This means that it must use a subquery to get
+ * the {@link Cols.Package#PACKAGE_ID} rather than the join which is already in place for that
+ * table.
+ */
+ protected AppQuerySelection querySingleForUpdate(String packageName, long repoId) {
+ final String selection = Cols.PACKAGE_ID + " = (" + getPackageIdFromPackageNameQuery() +
+ ") AND " + Cols.REPO_ID + " = ? ";
+ final String[] args = {packageName, Long.toString(repoId)};
+ return new AppQuerySelection(selection, args);
+ }
+
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
@@ -697,7 +734,10 @@ public class AppProvider extends FDroidProvider {
break;
case CODE_SINGLE:
- selection = selection.add(querySingle(uri.getLastPathSegment()));
+ List pathParts = uri.getPathSegments();
+ long repoId = Long.parseLong(pathParts.get(1));
+ String packageName = pathParts.get(2);
+ selection = selection.add(querySingle(packageName, repoId));
break;
case CAN_UPDATE:
@@ -799,11 +839,15 @@ public class AppProvider extends FDroidProvider {
@Override
public Uri insert(Uri uri, ContentValues values) {
+ long packageId = PackageProvider.Helper.ensureExists(getContext(), values.getAsString(Cols.Package.PACKAGE_NAME));
+ values.remove(Cols.Package.PACKAGE_NAME);
+ values.put(Cols.PACKAGE_ID, packageId);
+
db().insertOrThrow(getTableName(), null, values);
if (!isApplyingBatch()) {
getContext().getContentResolver().notifyChange(uri, null);
}
- return getContentUri(values.getAsString(Cols.PACKAGE_NAME));
+ return getAppUri(values.getAsString(PackageTable.Cols.PACKAGE_NAME), values.getAsLong(Cols.REPO_ID));
}
@Override
@@ -816,7 +860,10 @@ public class AppProvider extends FDroidProvider {
return 0;
case CODE_SINGLE:
- query = query.add(querySingle(uri.getLastPathSegment()));
+ List pathParts = uri.getPathSegments();
+ long repoId = Long.parseLong(pathParts.get(1));
+ String packageName = pathParts.get(2);
+ query = query.add(querySingleForUpdate(packageName, repoId));
break;
default:
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 14e87a7eb..d79335940 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java
@@ -103,7 +103,8 @@ class DBHelper extends SQLiteOpenHelper {
static final String CREATE_TABLE_APP_METADATA = "CREATE TABLE " + AppMetadataTable.NAME
+ " ( "
- + AppMetadataTable.Cols.PACKAGE_NAME + " text not null, "
+ + AppMetadataTable.Cols.PACKAGE_ID + " integer not null, "
+ + AppMetadataTable.Cols.REPO_ID + " integer not null, "
+ AppMetadataTable.Cols.NAME + " text not null, "
+ AppMetadataTable.Cols.SUMMARY + " text not null, "
+ AppMetadataTable.Cols.ICON + " text, "
@@ -130,7 +131,7 @@ class DBHelper extends SQLiteOpenHelper {
+ AppMetadataTable.Cols.IS_COMPATIBLE + " int not null,"
+ AppMetadataTable.Cols.ICON_URL + " text, "
+ AppMetadataTable.Cols.ICON_URL_LARGE + " text, "
- + "primary key(" + AppMetadataTable.Cols.PACKAGE_NAME + "));";
+ + "primary key(" + AppMetadataTable.Cols.PACKAGE_ID + ", " + AppMetadataTable.Cols.REPO_ID + "));";
private static final String CREATE_TABLE_APP_PREFS = "CREATE TABLE " + AppPrefsTable.NAME
+ " ( "
@@ -434,7 +435,7 @@ class DBHelper extends SQLiteOpenHelper {
+ AppPrefsTable.Cols.IGNORE_THIS_UPDATE + ", "
+ AppPrefsTable.Cols.IGNORE_ALL_UPDATES
+ ") SELECT "
- + AppMetadataTable.Cols.PACKAGE_NAME + ", "
+ + "id, "
+ "ignoreThisUpdate, "
+ "ignoreAllUpdates "
+ "FROM " + AppMetadataTable.NAME + " "
@@ -543,7 +544,7 @@ class DBHelper extends SQLiteOpenHelper {
final String update = "UPDATE " + ApkTable.NAME + " SET " + ApkTable.Cols.APP_ID + " = ( " +
"SELECT app." + AppMetadataTable.Cols.ROW_ID + " " +
"FROM " + AppMetadataTable.NAME + " AS app " +
- "WHERE " + ApkTable.NAME + ".id = app." + AppMetadataTable.Cols.PACKAGE_NAME + ")";
+ "WHERE " + ApkTable.NAME + ".id = app.id)";
Log.i(TAG, "Updating foreign key from " + ApkTable.NAME + " to " + AppMetadataTable.NAME + " to use numeric foreign key.");
Utils.debugLog(TAG, update);
db.execSQL(update);
@@ -840,10 +841,17 @@ class DBHelper extends SQLiteOpenHelper {
}
Utils.debugLog(TAG, "Ensuring indexes exist for " + AppMetadataTable.NAME);
- db.execSQL("CREATE INDEX IF NOT EXISTS app_id on " + AppMetadataTable.NAME + " (" + AppMetadataTable.Cols.PACKAGE_NAME + ");");
db.execSQL("CREATE INDEX IF NOT EXISTS name on " + AppMetadataTable.NAME + " (" + AppMetadataTable.Cols.NAME + ");"); // Used for sorting most lists
db.execSQL("CREATE INDEX IF NOT EXISTS added on " + AppMetadataTable.NAME + " (" + AppMetadataTable.Cols.ADDED + ");"); // Used for sorting "newly added"
+ if (columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.PACKAGE_ID)) {
+ db.execSQL("CREATE INDEX IF NOT EXISTS metadata_packageId ON " + AppMetadataTable.NAME + " (" + AppMetadataTable.Cols.PACKAGE_ID + ");");
+ }
+
+ if (columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.REPO_ID)) {
+ db.execSQL("CREATE INDEX IF NOT EXISTS metadata_repoId ON " + AppMetadataTable.NAME + " (" + AppMetadataTable.Cols.REPO_ID + ");");
+ }
+
Utils.debugLog(TAG, "Ensuring indexes exist for " + ApkTable.NAME);
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 + ");");
diff --git a/app/src/main/java/org/fdroid/fdroid/data/FDroidProvider.java b/app/src/main/java/org/fdroid/fdroid/data/FDroidProvider.java
index c1c046be7..26f6f28fb 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/FDroidProvider.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/FDroidProvider.java
@@ -157,4 +157,8 @@ public abstract class FDroidProvider extends ContentProvider {
}
}
}
+
+ protected String getPackageIdFromPackageNameQuery() {
+ return "SELECT " + Schema.PackageTable.Cols.ROW_ID + " FROM " + Schema.PackageTable.NAME + " WHERE " + Schema.PackageTable.Cols.PACKAGE_NAME + " = ?";
+ }
}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/PackageProvider.java b/app/src/main/java/org/fdroid/fdroid/data/PackageProvider.java
new file mode 100644
index 000000000..9c3d6942c
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/data/PackageProvider.java
@@ -0,0 +1,173 @@
+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.util.Log;
+
+import org.fdroid.fdroid.data.Schema.PackageTable;
+import org.fdroid.fdroid.data.Schema.PackageTable.Cols;
+
+public class PackageProvider extends FDroidProvider {
+
+ private static final String TAG = "PackageProvider";
+
+ public static final class Helper {
+ private Helper() { }
+
+ public static long ensureExists(Context context, String packageName) {
+ long id = getPackageId(context, packageName);
+ if (id <= 0) {
+ ContentValues values = new ContentValues(1);
+ values.put(Cols.PACKAGE_NAME, packageName);
+ Uri uri = context.getContentResolver().insert(getContentUri(), values);
+ id = Long.parseLong(uri.getLastPathSegment());
+ }
+ return id;
+ }
+
+ public static long getPackageId(Context context, String packageName) {
+ Cursor cursor = context.getContentResolver().query(getPackageUri(packageName), Cols.ALL, null, null, null);
+ if (cursor == null) {
+ return 0;
+ }
+
+ try {
+ if (cursor.getCount() == 0) {
+ return 0;
+ } else {
+ cursor.moveToFirst();
+ return cursor.getLong(cursor.getColumnIndexOrThrow(Cols.PACKAGE_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ private class Query extends QueryBuilder {
+
+ @Override
+ protected String getRequiredTables() {
+ return PackageTable.NAME;
+ }
+
+ @Override
+ public void addField(String field) {
+ appendField(field, getTableName());
+ }
+ }
+
+ private static final String PROVIDER_NAME = "PackageProvider";
+
+ private static final UriMatcher MATCHER = new UriMatcher(-1);
+
+ private static final String PATH_PACKAGE_NAME = "packageName";
+ private static final String PATH_PACKAGE_ID = "packageId";
+
+ static {
+ MATCHER.addURI(getAuthority(), PATH_PACKAGE_NAME + "/*", CODE_SINGLE);
+ }
+
+ private static Uri getContentUri() {
+ return Uri.parse("content://" + getAuthority());
+ }
+
+ public static Uri getPackageUri(String packageName) {
+ return getContentUri()
+ .buildUpon()
+ .appendPath(PATH_PACKAGE_NAME)
+ .appendPath(packageName)
+ .build();
+ }
+
+ /**
+ * Not actually used as part of the external API to this content provider.
+ * Rather, used as a mechanism for returning the ID of a newly inserted row after calling
+ * {@link android.content.ContentProvider#insert(Uri, ContentValues)}, as that is only able
+ * to return a {@link Uri}. The {@link Uri#getLastPathSegment()} of this URI contains a
+ * {@link Long} which is the {@link PackageTable.Cols#ROW_ID} of the newly inserted row.
+ */
+ private static Uri getPackageIdUri(long packageId) {
+ return getContentUri()
+ .buildUpon()
+ .appendPath(PATH_PACKAGE_ID)
+ .appendPath(Long.toString(packageId))
+ .build();
+ }
+
+ @Override
+ protected String getTableName() {
+ return PackageTable.NAME;
+ }
+
+ @Override
+ protected String getProviderName() {
+ return "PackageProvider";
+ }
+
+ 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) {
+ QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
+
+ switch (MATCHER.match(uri)) {
+ case CODE_SINGLE:
+ selection = selection.add(querySingle(uri.getLastPathSegment()));
+ break;
+
+ default:
+ Log.e(TAG, "Invalid URI for content provider: " + uri);
+ throw new UnsupportedOperationException("Invalid URI for content provider: " + uri);
+ }
+
+ 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;
+ }
+
+ /**
+ * Deleting of packages is not required.
+ * It doesn't matter if we have a package name in the database after the package is no longer
+ * present in the repo any more. They wont take up much space, and it is the presence of rows
+ * in the {@link Schema.MetadataTable} which decides whether something is available in the
+ * F-Droid client or not.
+ */
+ @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) {
+ long rowId = db().insertOrThrow(getTableName(), null, values);
+ getContext().getContentResolver().notifyChange(AppProvider.getCanUpdateUri(), null);
+ return getPackageIdUri(rowId);
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ throw new UnsupportedOperationException("Update not supported for " + uri + ".");
+ }
+}
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 68e2912fc..9e403af20 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/RepoPersister.java
@@ -143,7 +143,7 @@ public class RepoPersister {
for (App app : apps) {
packageNames.add(app.packageName);
}
- String[] projection = {Schema.AppMetadataTable.Cols.ROW_ID, Schema.AppMetadataTable.Cols.PACKAGE_NAME};
+ String[] projection = {Schema.AppMetadataTable.Cols.ROW_ID, Schema.AppMetadataTable.Cols.Package.PACKAGE_NAME};
List fromDb = TempAppProvider.Helper.findByPackageNames(context, packageNames, projection);
Map ids = new HashMap<>(fromDb.size());
@@ -175,7 +175,7 @@ public class RepoPersister {
*/
private ArrayList insertOrUpdateApks(List packages) {
String[] projection = new String[]{
- Schema.ApkTable.Cols.App.PACKAGE_NAME,
+ Schema.ApkTable.Cols.Package.PACKAGE_NAME,
Schema.ApkTable.Cols.VERSION_CODE,
};
List existingApks = ApkProvider.Helper.knownApks(context, packages, projection);
@@ -204,7 +204,7 @@ public class RepoPersister {
* Does not do any checks to see if the app already exists or not.
*/
private ContentProviderOperation updateExistingApp(App app) {
- Uri uri = TempAppProvider.getAppUri(app);
+ Uri uri = TempAppProvider.getAppUri(app.packageName, app.repoId);
return ContentProviderOperation.newUpdate(uri).withValues(app.toContentValues()).build();
}
@@ -224,8 +224,8 @@ public class RepoPersister {
* array.
*/
private boolean isAppInDatabase(App app) {
- String[] fields = {Schema.AppMetadataTable.Cols.PACKAGE_NAME};
- App found = AppProvider.Helper.findByPackageName(context.getContentResolver(), app.packageName, fields);
+ String[] fields = {Schema.AppMetadataTable.Cols.Package.PACKAGE_NAME};
+ App found = AppProvider.Helper.findByPackageName(context.getContentResolver(), app.packageName, repo.id, fields);
return found != null;
}
@@ -255,7 +255,7 @@ public class RepoPersister {
*/
@Nullable
private ContentProviderOperation deleteOrphanedApks(List apps, Map> packages) {
- String[] projection = new String[]{Schema.ApkTable.Cols.App.PACKAGE_NAME, Schema.ApkTable.Cols.VERSION_CODE};
+ String[] projection = new String[]{Schema.ApkTable.Cols.Package.PACKAGE_NAME, Schema.ApkTable.Cols.VERSION_CODE};
List existing = ApkProvider.Helper.find(context, repo, apps, projection);
List toDelete = new ArrayList<>();
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 b9037deab..eee638a18 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/Schema.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/Schema.java
@@ -53,7 +53,8 @@ public interface Schema {
String ROW_ID = "rowid";
String _COUNT = "_count";
String IS_COMPATIBLE = "compatible";
- String PACKAGE_NAME = "id";
+ String PACKAGE_ID = "packageId";
+ String REPO_ID = "repoId";
String NAME = "name";
String SUMMARY = "summary";
String ICON = "icon";
@@ -90,13 +91,17 @@ public interface Schema {
String SIGNATURE = "installedSig";
}
+ interface Package {
+ String PACKAGE_NAME = "package_packageName";
+ }
+
/**
* Each of the physical columns in the sqlite table. Differs from {@link Cols#ALL} in
* that it doesn't include fields which are aliases of other fields (e.g. {@link Cols#_ID}
* or which are from other related tables (e.g. {@link Cols.SuggestedApk#VERSION_NAME}).
*/
String[] ALL_COLS = {
- ROW_ID, IS_COMPATIBLE, PACKAGE_NAME, NAME, SUMMARY, ICON, DESCRIPTION,
+ ROW_ID, PACKAGE_ID, IS_COMPATIBLE, NAME, SUMMARY, ICON, DESCRIPTION,
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,
@@ -110,14 +115,14 @@ public interface Schema {
* @see Cols#ALL_COLS
*/
String[] ALL = {
- _ID, ROW_ID, IS_COMPATIBLE, PACKAGE_NAME, NAME, SUMMARY, ICON, DESCRIPTION,
+ _ID, ROW_ID, IS_COMPATIBLE, NAME, SUMMARY, ICON, DESCRIPTION,
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, ICON_URL, ICON_URL_LARGE,
SUGGESTED_VERSION_CODE, SuggestedApk.VERSION_NAME,
InstalledApp.VERSION_CODE, InstalledApp.VERSION_NAME,
- InstalledApp.SIGNATURE,
+ InstalledApp.SIGNATURE, Package.PACKAGE_NAME
};
}
}
@@ -163,8 +168,8 @@ public interface Schema {
String ADDRESS = "repoAddress";
}
- interface App {
- String PACKAGE_NAME = "appPackageName";
+ interface Package {
+ String PACKAGE_NAME = "package_packageName";
}
/**
@@ -181,7 +186,7 @@ public interface Schema {
* @see AppMetadataTable.Cols#ALL
*/
String[] ALL = {
- _ID, APP_ID, App.PACKAGE_NAME, VERSION_NAME, REPO_ID, HASH, VERSION_CODE, NAME,
+ _ID, APP_ID, Package.PACKAGE_NAME, VERSION_NAME, REPO_ID, HASH, VERSION_CODE, NAME,
SIZE, SIGNATURE, SOURCE_NAME, MIN_SDK_VERSION, TARGET_SDK_VERSION, MAX_SDK_VERSION,
PERMISSIONS, FEATURES, NATIVE_CODE, HASH_TYPE, ADDED_DATE,
IS_COMPATIBLE, Repo.VERSION, Repo.ADDRESS, INCOMPATIBLE_REASONS,
diff --git a/app/src/main/java/org/fdroid/fdroid/data/TempAppProvider.java b/app/src/main/java/org/fdroid/fdroid/data/TempAppProvider.java
index 955e82cde..9927fc28d 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/TempAppProvider.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/TempAppProvider.java
@@ -13,6 +13,7 @@ import java.util.List;
import org.fdroid.fdroid.data.Schema.ApkTable;
import org.fdroid.fdroid.data.Schema.AppMetadataTable;
+import org.fdroid.fdroid.data.Schema.PackageTable;
/**
* This class does all of its operations in a temporary sqlite table.
@@ -41,7 +42,7 @@ public class TempAppProvider extends AppProvider {
MATCHER.addURI(getAuthority(), PATH_INIT, CODE_INIT);
MATCHER.addURI(getAuthority(), PATH_COMMIT, CODE_COMMIT);
MATCHER.addURI(getAuthority(), PATH_APPS + "/*", APPS);
- MATCHER.addURI(getAuthority(), "*", CODE_SINGLE);
+ MATCHER.addURI(getAuthority(), PATH_APP + "/#/*", CODE_SINGLE);
}
@Override
@@ -57,8 +58,13 @@ public class TempAppProvider extends AppProvider {
return Uri.parse("content://" + getAuthority());
}
- public static Uri getAppUri(App app) {
- return Uri.withAppendedPath(getContentUri(), app.packageName);
+ public static Uri getAppUri(String packageName, long repoId) {
+ return getContentUri()
+ .buildUpon()
+ .appendPath(PATH_APP)
+ .appendPath(Long.toString(repoId))
+ .appendPath(packageName)
+ .build();
}
public static Uri getAppsUri(List apps) {
@@ -69,7 +75,7 @@ public class TempAppProvider extends AppProvider {
}
private AppQuerySelection queryApps(String packageNames) {
- return queryPackageNames(packageNames, getTableName() + "." + AppMetadataTable.Cols.PACKAGE_NAME);
+ return queryPackageNames(packageNames, PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
}
public static class Helper {
@@ -126,7 +132,13 @@ public class TempAppProvider extends AppProvider {
throw new UnsupportedOperationException("Update not supported for " + uri + ".");
}
- QuerySelection query = new QuerySelection(where, whereArgs).add(querySingle(uri.getLastPathSegment()));
+ List pathParts = uri.getPathSegments();
+ String packageName = pathParts.get(2);
+ long repoId = Long.parseLong(pathParts.get(1));
+ QuerySelection query = new QuerySelection(where, whereArgs).add(querySingleForUpdate(packageName, repoId));
+
+ // Package names for apps cannot change...
+ values.remove(AppMetadataTable.Cols.Package.PACKAGE_NAME);
int count = db().update(getTableName(), values, query.getSelection(), query.getArgs());
if (!isApplyingBatch()) {
@@ -163,7 +175,7 @@ public class TempAppProvider extends AppProvider {
db.execSQL("ATTACH DATABASE ':memory:' AS " + DB);
db.execSQL(DBHelper.CREATE_TABLE_APP_METADATA.replaceFirst(AppMetadataTable.NAME, DB + "." + getTableName()));
db.execSQL(copyData(AppMetadataTable.Cols.ALL_COLS, AppMetadataTable.NAME, DB + "." + getTableName()));
- db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_id ON " + getTableName() + " (" + AppMetadataTable.Cols.PACKAGE_NAME + ");");
+ db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_id ON " + getTableName() + " (" + AppMetadataTable.Cols.PACKAGE_ID + ");");
db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_upstreamVercode ON " + getTableName() + " (" + AppMetadataTable.Cols.UPSTREAM_VERSION_CODE + ");");
db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_compatible ON " + getTableName() + " (" + AppMetadataTable.Cols.IS_COMPATIBLE + ");");
}
diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
index 2e3564507..d97e58341 100644
--- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
+++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
@@ -259,7 +259,7 @@ public class InstallManagerService extends Service {
App app = getAppFromActive(downloadUrl);
if (app == null) {
ContentResolver resolver = context.getContentResolver();
- app = AppProvider.Helper.findByPackageName(resolver, apk.packageName);
+ app = AppProvider.Helper.findByPackageName(resolver, apk.packageName, apk.repo);
}
// show notification if app details is not visible
if (app != null && AppDetails.isAppVisible(app.packageName)) {
@@ -346,7 +346,7 @@ public class InstallManagerService extends Service {
String name = getAppName(apk);
if (TextUtils.isEmpty(name) || name.equals(new App().name)) {
ContentResolver resolver = getContentResolver();
- App app = AppProvider.Helper.findByPackageName(resolver, apk.packageName);
+ App app = AppProvider.Helper.findByPackageName(resolver, apk.packageName, apk.repo);
if (app == null || TextUtils.isEmpty(app.name)) {
return; // do not have a name to display, so leave notification as is
}
diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
index a14996357..967df1ac5 100644
--- a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
+++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
@@ -191,7 +191,7 @@ public class InstallConfirmActivity extends FragmentActivity implements OnCancel
intent = getIntent();
Uri uri = intent.getData();
Apk apk = ApkProvider.Helper.findByUri(this, uri, Schema.ApkTable.Cols.ALL);
- app = AppProvider.Helper.findByPackageName(getContentResolver(), apk.packageName);
+ app = AppProvider.Helper.findByPackageName(getContentResolver(), apk.packageName, apk.repo, Schema.AppMetadataTable.Cols.ALL);
appDiff = new AppDiff(getPackageManager(), apk);
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 7ffa038b5..188861f01 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
@@ -39,7 +39,7 @@ public abstract class AppListFragment extends ListFragment implements
private static final String[] APP_PROJECTION = {
AppMetadataTable.Cols._ID, // Required for cursor loader to work.
- AppMetadataTable.Cols.PACKAGE_NAME,
+ AppMetadataTable.Cols.Package.PACKAGE_NAME,
AppMetadataTable.Cols.NAME,
AppMetadataTable.Cols.SUMMARY,
AppMetadataTable.Cols.IS_COMPATIBLE,
diff --git a/app/src/main/java/org/fdroid/fdroid/views/swap/SwapAppsView.java b/app/src/main/java/org/fdroid/fdroid/views/swap/SwapAppsView.java
index 0b570506c..d14f831f4 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/swap/SwapAppsView.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/swap/SwapAppsView.java
@@ -289,7 +289,8 @@ public class SwapAppsView extends ListView implements
public void onChange(boolean selfChange) {
Activity activity = getActivity();
if (activity != null) {
- app = AppProvider.Helper.findByPackageName(getActivity().getContentResolver(), app.packageName);
+ app = AppProvider.Helper.findByPackageName(getActivity().getContentResolver(),
+ app.packageName, app.repoId, AppMetadataTable.Cols.ALL);
resetView();
}
}
@@ -318,7 +319,7 @@ public class SwapAppsView extends ListView implements
// implemented on API-16, so leaving like this for now.
getActivity().getContentResolver().unregisterContentObserver(appObserver);
getActivity().getContentResolver().registerContentObserver(
- AppProvider.getContentUri(this.app.packageName), true, appObserver);
+ AppProvider.getAppUri(this.app), true, appObserver);
}
resetView();
}
diff --git a/app/src/test/java/org/fdroid/fdroid/Assert.java b/app/src/test/java/org/fdroid/fdroid/Assert.java
index 61f6fe223..adbd30db4 100644
--- a/app/src/test/java/org/fdroid/fdroid/Assert.java
+++ b/app/src/test/java/org/fdroid/fdroid/Assert.java
@@ -183,7 +183,8 @@ public class Assert {
public static App insertApp(Context context, String packageName, String name, ContentValues additionalValues) {
ContentValues values = new ContentValues();
- values.put(AppMetadataTable.Cols.PACKAGE_NAME, packageName);
+ values.put(AppMetadataTable.Cols.REPO_ID, 1);
+ values.put(AppMetadataTable.Cols.Package.PACKAGE_NAME, packageName);
values.put(AppMetadataTable.Cols.NAME, name);
// Required fields (NOT NULL in the database).
@@ -197,14 +198,14 @@ public class Assert {
Uri uri = AppProvider.getContentUri();
context.getContentResolver().insert(uri, values);
- return AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName);
+ return AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName, 1);
}
private static App ensureApp(Context context, String packageName) {
- App app = AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName);
+ App app = AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName, 1);
if (app == null) {
insertApp(context, packageName, packageName);
- app = AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName);
+ app = AppProvider.Helper.findByPackageName(context.getContentResolver(), packageName, 1);
}
assertNotNull(app);
return app;
diff --git a/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java
index 95a153071..efbfada6e 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java
@@ -284,7 +284,7 @@ public class ApkProviderTest extends FDroidProviderTest {
Collections.addAll(apksToCheck, unknown);
String[] projection = {
- Cols.App.PACKAGE_NAME,
+ Cols.Package.PACKAGE_NAME,
Cols.VERSION_CODE,
};
@@ -424,7 +424,7 @@ public class ApkProviderTest extends FDroidProviderTest {
assertEquals("a hash type", apk.hashType);
String[] projection = {
- Cols.App.PACKAGE_NAME,
+ Cols.Package.PACKAGE_NAME,
Cols.HASH,
};
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 f6dd4995a..b0ccd5e6e 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
@@ -68,7 +68,7 @@ public class AppProviderTest extends FDroidProviderTest {
@Test
public void testCantFindApp() {
- assertNull(AppProvider.Helper.findByPackageName(context.getContentResolver(), "com.example.doesnt-exist"));
+ assertNull(AppProvider.Helper.findByPackageName(context.getContentResolver(), "com.example.doesnt-exist", 1));
}
@Test
@@ -111,14 +111,14 @@ public class AppProviderTest extends FDroidProviderTest {
ContentResolver r = context.getContentResolver();
// Can't "update", although can "install"...
- App notInstalled = AppProvider.Helper.findByPackageName(r, "not installed");
+ App notInstalled = AppProvider.Helper.findByPackageName(r, "not installed", 1);
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");
- App installedAlreadyLatestIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore all");
- App installedAlreadyLatestIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore latest");
- App installedAlreadyLatestIgnoreOld = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore old");
+ App installedOnlyOneVersionAvailable = AppProvider.Helper.findByPackageName(r, "installed, only one version available", 1);
+ App installedAlreadyLatestNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, already latest, no ignore", 1);
+ App installedAlreadyLatestIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore all", 1);
+ App installedAlreadyLatestIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore latest", 1);
+ App installedAlreadyLatestIgnoreOld = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore old", 1);
assertFalse(installedOnlyOneVersionAvailable.canAndWantToUpdate(context));
assertFalse(installedAlreadyLatestNoIgnore.canAndWantToUpdate(context));
@@ -126,10 +126,10 @@ public class AppProviderTest extends FDroidProviderTest {
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");
+ App installedOldNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, old version, no ignore", 1);
+ App installedOldIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore all", 1);
+ App installedOldIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore latest", 1);
+ App installedOldIgnoreNewerNotLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore newer, but not latest", 1);
assertTrue(installedOldNoIgnore.canAndWantToUpdate(context));
assertFalse(installedOldIgnoreAll.canAndWantToUpdate(context));
@@ -169,7 +169,7 @@ public class AppProviderTest extends FDroidProviderTest {
assertResultCount(contentResolver, 10, AppProvider.getContentUri(), PROJ);
- String[] projection = {Cols.PACKAGE_NAME};
+ String[] projection = {Cols.Package.PACKAGE_NAME};
List canUpdateApps = AppProvider.Helper.findCanUpdate(context, projection);
String[] expectedCanUpdate = {
@@ -239,7 +239,7 @@ public class AppProviderTest extends FDroidProviderTest {
assertEquals("org.fdroid.fdroid", app.packageName);
assertEquals("F-Droid", app.name);
- App otherApp = AppProvider.Helper.findByPackageName(context.getContentResolver(), "org.fdroid.fdroid");
+ App otherApp = AppProvider.Helper.findByPackageName(context.getContentResolver(), "org.fdroid.fdroid", 1);
assertNotNull(otherApp);
assertEquals("org.fdroid.fdroid", otherApp.packageName);
assertEquals("F-Droid", otherApp.name);
@@ -260,7 +260,7 @@ public class AppProviderTest extends FDroidProviderTest {
String[] projection = new String[] {
Cols._ID,
Cols.NAME,
- Cols.PACKAGE_NAME,
+ Cols.Package.PACKAGE_NAME,
};
return contentResolver.query(AppProvider.getContentUri(), projection, null, null, null);
}
@@ -356,7 +356,8 @@ public class AppProviderTest extends FDroidProviderTest {
public App insertApp(String id, String name, ContentValues additionalValues) {
ContentValues values = new ContentValues();
- values.put(Cols.PACKAGE_NAME, id);
+ values.put(Cols.Package.PACKAGE_NAME, id);
+ values.put(Cols.REPO_ID, 1);
values.put(Cols.NAME, name);
// Required fields (NOT NULL in the database).
@@ -370,6 +371,6 @@ public class AppProviderTest extends FDroidProviderTest {
Uri uri = AppProvider.getContentUri();
contentResolver.insert(uri, values);
- return AppProvider.Helper.findByPackageName(context.getContentResolver(), id);
+ return AppProvider.Helper.findByPackageName(context.getContentResolver(), id, 1);
}
}
diff --git a/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java b/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java
index 2c5f067e0..5f4d445bb 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java
@@ -93,10 +93,10 @@ public class ProviderUriTests {
assertValidUri(resolver, AppProvider.getCanUpdateUri(), "content://org.fdroid.fdroid.data.AppProvider/canUpdate", projection);
App app = new App();
+ app.repoId = 1;
app.packageName = "org.fdroid.fdroid";
- assertValidUri(resolver, AppProvider.getContentUri(app), "content://org.fdroid.fdroid.data.AppProvider/org.fdroid.fdroid", projection);
- assertValidUri(resolver, AppProvider.getContentUri("org.fdroid.fdroid"), "content://org.fdroid.fdroid.data.AppProvider/org.fdroid.fdroid", projection);
+ assertValidUri(resolver, AppProvider.getAppUri(app), "content://org.fdroid.fdroid.data.AppProvider/app/1/org.fdroid.fdroid", projection);
}
@Test