Added new table to store user preferences.
Haven't yet migrated data from the old location in the app table yet.
This commit is contained in:
parent
3c5f8756f4
commit
d47967e03d
@ -95,6 +95,11 @@
|
|||||||
android:name="org.fdroid.fdroid.data.InstalledAppProvider"
|
android:name="org.fdroid.fdroid.data.InstalledAppProvider"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:authorities="org.fdroid.fdroid.data.AppPrefsProvider"
|
||||||
|
android:name="org.fdroid.fdroid.data.AppPrefsProvider"
|
||||||
|
android:exported="false"/>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="org.fdroid.fdroid.installer.ApkFileProvider"
|
android:name="org.fdroid.fdroid.installer.ApkFileProvider"
|
||||||
android:authorities="org.fdroid.fdroid.installer.ApkFileProvider"
|
android:authorities="org.fdroid.fdroid.installer.ApkFileProvider"
|
||||||
|
24
app/src/main/java/org/fdroid/fdroid/data/AppPrefs.java
Normal file
24
app/src/main/java/org/fdroid/fdroid/data/AppPrefs.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package org.fdroid.fdroid.data;
|
||||||
|
|
||||||
|
public class AppPrefs extends ValueObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if all updates for this app are to be ignored
|
||||||
|
*/
|
||||||
|
public final boolean ignoreAllUpdates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the current update for this app is to be ignored
|
||||||
|
*/
|
||||||
|
public final int ignoreThisUpdate;
|
||||||
|
|
||||||
|
public AppPrefs(int ignoreThis, boolean ignoreAll) {
|
||||||
|
ignoreThisUpdate = ignoreThis;
|
||||||
|
ignoreAllUpdates = ignoreAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AppPrefs createDefault() {
|
||||||
|
return new AppPrefs(0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
173
app/src/main/java/org/fdroid/fdroid/data/AppPrefsProvider.java
Normal file
173
app/src/main/java/org/fdroid/fdroid/data/AppPrefsProvider.java
Normal file
@ -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.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.data.Schema.AppPrefsTable;
|
||||||
|
import org.fdroid.fdroid.data.Schema.AppPrefsTable.Cols;
|
||||||
|
|
||||||
|
public class AppPrefsProvider extends FDroidProvider {
|
||||||
|
|
||||||
|
private static final String TAG = "AppPrefsProvider";
|
||||||
|
|
||||||
|
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.APP_ID, app.getId());
|
||||||
|
context.getContentResolver().insert(getContentUri(), values);
|
||||||
|
} else {
|
||||||
|
context.getContentResolver().update(getAppUri(app.getId()), 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.getId()), Cols.ALL, null, null, null);
|
||||||
|
if (cursor == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cursor.getCount() == 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
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_APP_ID = "appId";
|
||||||
|
|
||||||
|
static {
|
||||||
|
MATCHER.addURI(getAuthority(), PATH_APP_ID + "/#", CODE_SINGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Uri getContentUri() {
|
||||||
|
return Uri.parse("content://" + getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Uri getAppUri(long appId) {
|
||||||
|
return getContentUri().buildUpon().appendPath(PATH_APP_ID).appendPath(Long.toString(appId)).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(long appId) {
|
||||||
|
final String selection = getTableName() + "." + Cols.APP_ID + " = ?";
|
||||||
|
final String[] args = {Long.toString(appId)};
|
||||||
|
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(Long.parseLong(uri.getLastPathSegment())));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Invalid URI for app content provider: " + uri);
|
||||||
|
throw new UnsupportedOperationException("Invalid URI for app 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String where, String[] whereArgs) {
|
||||||
|
switch (MATCHER.match(uri)) {
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Delete not supported for " + uri + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
db().insertOrThrow(getTableName(), null, values);
|
||||||
|
if (!isApplyingBatch()) {
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
}
|
||||||
|
return getAppUri(values.getAsLong(Cols.APP_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
|
||||||
|
switch (MATCHER.match(uri)) {
|
||||||
|
case CODE_SINGLE:
|
||||||
|
QuerySelection query = new QuerySelection(where, whereArgs)
|
||||||
|
.add(querySingle(Long.parseLong(uri.getLastPathSegment())));
|
||||||
|
return db().update(getTableName(), values, query.getSelection(), query.getArgs());
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Update not supported for " + uri + ".");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import android.util.Log;
|
|||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.data.Schema.ApkTable;
|
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;
|
||||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
||||||
import org.fdroid.fdroid.data.Schema.RepoTable;
|
import org.fdroid.fdroid.data.Schema.RepoTable;
|
||||||
@ -101,6 +102,13 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
+ AppTable.Cols.ICON_URL_LARGE + " text, "
|
+ AppTable.Cols.ICON_URL_LARGE + " text, "
|
||||||
+ "primary key(" + AppTable.Cols.PACKAGE_NAME + "));";
|
+ "primary key(" + AppTable.Cols.PACKAGE_NAME + "));";
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_APP_PREFS = "CREATE TABLE " + AppPrefsTable.NAME
|
||||||
|
+ " ( "
|
||||||
|
+ AppPrefsTable.Cols.APP_ID + " INT REFERENCES " + AppTable.NAME + "(" + AppTable.Cols.ROW_ID + ") ON DELETE CASCADE, "
|
||||||
|
+ 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
|
private static final String CREATE_TABLE_INSTALLED_APP = "CREATE TABLE " + InstalledAppTable.NAME
|
||||||
+ " ( "
|
+ " ( "
|
||||||
+ InstalledAppTable.Cols.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY, "
|
+ InstalledAppTable.Cols.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY, "
|
||||||
@ -219,6 +227,7 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
createAppApk(db);
|
createAppApk(db);
|
||||||
db.execSQL(CREATE_TABLE_INSTALLED_APP);
|
db.execSQL(CREATE_TABLE_INSTALLED_APP);
|
||||||
db.execSQL(CREATE_TABLE_REPO);
|
db.execSQL(CREATE_TABLE_REPO);
|
||||||
|
db.execSQL(CREATE_TABLE_APP_PREFS);
|
||||||
|
|
||||||
insertRepo(
|
insertRepo(
|
||||||
db,
|
db,
|
||||||
|
@ -9,6 +9,19 @@ import android.provider.BaseColumns;
|
|||||||
*/
|
*/
|
||||||
public interface Schema {
|
public interface Schema {
|
||||||
|
|
||||||
|
interface AppPrefsTable {
|
||||||
|
|
||||||
|
String NAME = "fdroid_appPrefs";
|
||||||
|
|
||||||
|
interface Cols extends BaseColumns {
|
||||||
|
String APP_ID = "appId";
|
||||||
|
String IGNORE_ALL_UPDATES = "ignoreAllUpdates";
|
||||||
|
String IGNORE_THIS_UPDATE = "ignoreThisUpdate";
|
||||||
|
|
||||||
|
String[] ALL = {APP_ID, IGNORE_ALL_UPDATES, IGNORE_THIS_UPDATE,};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface AppTable {
|
interface AppTable {
|
||||||
|
|
||||||
String NAME = "fdroid_app";
|
String NAME = "fdroid_app";
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package org.fdroid.fdroid.data;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.Assert;
|
||||||
|
import org.fdroid.fdroid.BuildConfig;
|
||||||
|
import org.fdroid.fdroid.TestUtils;
|
||||||
|
import org.fdroid.fdroid.data.Schema.AppPrefsTable.Cols;
|
||||||
|
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 junit.framework.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
@Config(constants = BuildConfig.class, application = Application.class)
|
||||||
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
|
public class AppPrefsProviderTest extends FDroidProviderTest {
|
||||||
|
|
||||||
|
private static final String[] PROJ = Cols.ALL;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user