Merge branch 'preperation-for-new-ui' into 'master'
Some groundwork for the main screens new UI See merge request !432
This commit is contained in:
		
						commit
						3ca3a6d699
					
				@ -6,6 +6,7 @@ import android.content.Context;
 | 
			
		||||
import android.content.UriMatcher;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
@ -378,11 +379,13 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
    private static final String PATH_HIGHEST_PRIORITY = "highestPriority";
 | 
			
		||||
    private static final String PATH_CALC_PREFERRED_METADATA = "calcPreferredMetadata";
 | 
			
		||||
    private static final String PATH_CALC_SUGGESTED_APKS = "calcNonRepoDetailsFromIndex";
 | 
			
		||||
    private static final String PATH_TOP_FROM_CATEGORY = "topFromCategory";
 | 
			
		||||
 | 
			
		||||
    private static final int CAN_UPDATE = CODE_SINGLE + 1;
 | 
			
		||||
    private static final int INSTALLED = CAN_UPDATE + 1;
 | 
			
		||||
    private static final int SEARCH = INSTALLED + 1;
 | 
			
		||||
    private static final int RECENTLY_UPDATED = SEARCH + 1;
 | 
			
		||||
    private static final int SEARCH_TEXT = INSTALLED + 1;
 | 
			
		||||
    private static final int SEARCH_TEXT_AND_CATEGORIES = SEARCH_TEXT + 1;
 | 
			
		||||
    private static final int RECENTLY_UPDATED = SEARCH_TEXT_AND_CATEGORIES + 1;
 | 
			
		||||
    private static final int NEWLY_ADDED = RECENTLY_UPDATED + 1;
 | 
			
		||||
    private static final int CATEGORY = NEWLY_ADDED + 1;
 | 
			
		||||
    private static final int CALC_SUGGESTED_APKS = CATEGORY + 1;
 | 
			
		||||
@ -392,6 +395,7 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
    private static final int SEARCH_CAN_UPDATE = SEARCH_INSTALLED + 1;
 | 
			
		||||
    private static final int HIGHEST_PRIORITY = SEARCH_CAN_UPDATE + 1;
 | 
			
		||||
    private static final int CALC_PREFERRED_METADATA = HIGHEST_PRIORITY + 1;
 | 
			
		||||
    private static final int TOP_FROM_CATEGORY = CALC_PREFERRED_METADATA + 1;
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        MATCHER.addURI(getAuthority(), null, CODE_LIST);
 | 
			
		||||
@ -399,7 +403,8 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_RECENTLY_UPDATED, RECENTLY_UPDATED);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_NEWLY_ADDED, NEWLY_ADDED);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_CATEGORY + "/*", CATEGORY);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*", SEARCH);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*/*", SEARCH_TEXT_AND_CATEGORIES);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*", SEARCH_TEXT);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH_INSTALLED + "/*", SEARCH_INSTALLED);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH_CAN_UPDATE + "/*", SEARCH_CAN_UPDATE);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SEARCH_REPO + "/*/*", SEARCH_REPO);
 | 
			
		||||
@ -409,6 +414,7 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_HIGHEST_PRIORITY + "/*", HIGHEST_PRIORITY);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_SPECIFIC_APP + "/#/*", CODE_SINGLE);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_CALC_PREFERRED_METADATA, CALC_PREFERRED_METADATA);
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_TOP_FROM_CATEGORY + "/#/*", TOP_FROM_CATEGORY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Uri getContentUri() {
 | 
			
		||||
@ -429,9 +435,17 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
 | 
			
		||||
    public static Uri getCategoryUri(String category) {
 | 
			
		||||
        return getContentUri().buildUpon()
 | 
			
		||||
            .appendPath(PATH_CATEGORY)
 | 
			
		||||
            .appendPath(category)
 | 
			
		||||
            .build();
 | 
			
		||||
                .appendPath(PATH_CATEGORY)
 | 
			
		||||
                .appendPath(category)
 | 
			
		||||
                .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Uri getTopFromCategoryUri(String category, int limit) {
 | 
			
		||||
        return getContentUri().buildUpon()
 | 
			
		||||
                .appendPath(PATH_TOP_FROM_CATEGORY)
 | 
			
		||||
                .appendPath(Integer.toString(limit))
 | 
			
		||||
                .appendPath(category)
 | 
			
		||||
                .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Uri getInstalledUri() {
 | 
			
		||||
@ -478,15 +492,23 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        return Uri.withAppendedPath(getContentUri(), packageName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Uri getSearchUri(String query) {
 | 
			
		||||
        if (TextUtils.isEmpty(query)) {
 | 
			
		||||
    public static Uri getSearchUri(String query, @Nullable String category) {
 | 
			
		||||
        if (TextUtils.isEmpty(query) && TextUtils.isEmpty(category)) {
 | 
			
		||||
            // Return all the things for an empty search.
 | 
			
		||||
            return getContentUri();
 | 
			
		||||
        } else if (TextUtils.isEmpty(query)) {
 | 
			
		||||
            return getCategoryUri(category);
 | 
			
		||||
        }
 | 
			
		||||
        return getContentUri().buildUpon()
 | 
			
		||||
 | 
			
		||||
        Uri.Builder builder = getContentUri().buildUpon()
 | 
			
		||||
                .appendPath(PATH_SEARCH)
 | 
			
		||||
                .appendPath(query)
 | 
			
		||||
                .build();
 | 
			
		||||
                .appendPath(query);
 | 
			
		||||
 | 
			
		||||
        if (!TextUtils.isEmpty(category)) {
 | 
			
		||||
            builder.appendPath(category);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return builder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Uri getSearchInstalledUri(String query) {
 | 
			
		||||
@ -583,7 +605,6 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        final String app = getTableName();
 | 
			
		||||
        final String[] columns = {
 | 
			
		||||
                PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME,
 | 
			
		||||
                CategoryTable.NAME + "." + CategoryTable.Cols.NAME,
 | 
			
		||||
                app + "." + Cols.NAME,
 | 
			
		||||
                app + "." + Cols.SUMMARY,
 | 
			
		||||
                app + "." + Cols.DESCRIPTION,
 | 
			
		||||
@ -676,7 +697,14 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private AppQuerySelection queryCategory(String category) {
 | 
			
		||||
        final String selection = CategoryTable.NAME + "." + CategoryTable.Cols.NAME + " = ? ";
 | 
			
		||||
        if (TextUtils.isEmpty(category)) {
 | 
			
		||||
            return new AppQuerySelection();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Note, the COLLATE NOCASE only works for ASCII columns. The "ICU extension" for SQLite
 | 
			
		||||
        // provides proper case management for Unicode characters, but is not something provided
 | 
			
		||||
        // by Android.
 | 
			
		||||
        final String selection = CategoryTable.NAME + "." + CategoryTable.Cols.NAME + " = ? COLLATE NOCASE ";
 | 
			
		||||
        final String[] args = {category};
 | 
			
		||||
        return new AppQuerySelection(selection, args);
 | 
			
		||||
    }
 | 
			
		||||
@ -702,6 +730,9 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        // querying from.
 | 
			
		||||
        boolean repoIsKnown = false;
 | 
			
		||||
 | 
			
		||||
        int limit = 0;
 | 
			
		||||
 | 
			
		||||
        List<String> pathSegments = uri.getPathSegments();
 | 
			
		||||
        switch (MATCHER.match(uri)) {
 | 
			
		||||
            case CALC_PREFERRED_METADATA:
 | 
			
		||||
                updatePreferredMetadata();
 | 
			
		||||
@ -712,9 +743,8 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case CODE_SINGLE:
 | 
			
		||||
                List<String> pathParts = uri.getPathSegments();
 | 
			
		||||
                long repoId = Long.parseLong(pathParts.get(1));
 | 
			
		||||
                String packageName = pathParts.get(2);
 | 
			
		||||
                long repoId = Long.parseLong(pathSegments.get(1));
 | 
			
		||||
                String packageName = pathSegments.get(2);
 | 
			
		||||
                selection = selection.add(querySingle(packageName, repoId));
 | 
			
		||||
                repoIsKnown = true;
 | 
			
		||||
                break;
 | 
			
		||||
@ -734,8 +764,15 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
                includeSwap = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case SEARCH:
 | 
			
		||||
                selection = selection.add(querySearch(uri.getLastPathSegment()));
 | 
			
		||||
            case SEARCH_TEXT:
 | 
			
		||||
                selection = selection.add(querySearch(pathSegments.get(1)));
 | 
			
		||||
                includeSwap = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case SEARCH_TEXT_AND_CATEGORIES:
 | 
			
		||||
                selection = selection
 | 
			
		||||
                        .add(querySearch(pathSegments.get(1)))
 | 
			
		||||
                        .add(queryCategory(pathSegments.get(2)));
 | 
			
		||||
                includeSwap = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
@ -751,8 +788,8 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
 | 
			
		||||
            case SEARCH_REPO:
 | 
			
		||||
                selection = selection
 | 
			
		||||
                        .add(querySearch(uri.getPathSegments().get(2)))
 | 
			
		||||
                        .add(queryRepo(Long.parseLong(uri.getPathSegments().get(1))));
 | 
			
		||||
                        .add(querySearch(pathSegments.get(2)))
 | 
			
		||||
                        .add(queryRepo(Long.parseLong(pathSegments.get(1))));
 | 
			
		||||
                repoIsKnown = true;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
@ -761,6 +798,12 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
                includeSwap = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case TOP_FROM_CATEGORY:
 | 
			
		||||
                selection = selection.add(queryCategory(pathSegments.get(2)));
 | 
			
		||||
                limit = Integer.parseInt(pathSegments.get(1));
 | 
			
		||||
                includeSwap = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case RECENTLY_UPDATED:
 | 
			
		||||
                sortOrder = getTableName() + "." + Cols.LAST_UPDATED + " DESC";
 | 
			
		||||
                selection = selection.add(queryRecentlyUpdated());
 | 
			
		||||
@ -787,14 +830,14 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
            selection = selection.add(queryHighestPriority());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return runQuery(uri, selection, projection, includeSwap, sortOrder);
 | 
			
		||||
        return runQuery(uri, selection, projection, includeSwap, sortOrder, limit);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Helper method used by both the genuine {@link AppProvider} and the temporary version used
 | 
			
		||||
     * by the repo updater ({@link TempAppProvider}).
 | 
			
		||||
     */
 | 
			
		||||
    protected Cursor runQuery(Uri uri, AppQuerySelection selection, String[] projection, boolean includeSwap, String sortOrder) {
 | 
			
		||||
    protected Cursor runQuery(Uri uri, AppQuerySelection selection, String[] projection, boolean includeSwap, String sortOrder, int limit) {
 | 
			
		||||
        if (!includeSwap) {
 | 
			
		||||
            selection = selection.add(queryExcludeSwap());
 | 
			
		||||
        }
 | 
			
		||||
@ -807,6 +850,7 @@ public class AppProvider extends FDroidProvider {
 | 
			
		||||
        query.addSelection(selection);
 | 
			
		||||
        query.addFields(projection); // TODO: Make the order of addFields/addSelection not dependent on each other...
 | 
			
		||||
        query.addOrderBy(sortOrder);
 | 
			
		||||
        query.addLimit(limit);
 | 
			
		||||
 | 
			
		||||
        Cursor cursor = LoggingQuery.query(db(), query.toString(), query.getArgs());
 | 
			
		||||
        cursor.setNotificationUri(getContext().getContentResolver(), uri);
 | 
			
		||||
 | 
			
		||||
@ -134,7 +134,7 @@ public class CategoryProvider extends FDroidProvider {
 | 
			
		||||
        MATCHER.addURI(getAuthority(), PATH_ALL_CATEGORIES, CODE_LIST);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Uri getContentUri() {
 | 
			
		||||
    static Uri getContentUri() {
 | 
			
		||||
        return Uri.parse("content://" + getAuthority());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -185,7 +185,7 @@ public class CategoryProvider extends FDroidProvider {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected QuerySelection querySingle(String categoryName) {
 | 
			
		||||
        final String selection = getTableName() + "." + Cols.NAME + " = ?";
 | 
			
		||||
        final String selection = getTableName() + "." + Cols.NAME + " = ? COLLATE NOCASE";
 | 
			
		||||
        final String[] args = {categoryName};
 | 
			
		||||
        return new QuerySelection(selection, args);
 | 
			
		||||
    }
 | 
			
		||||
@ -239,7 +239,9 @@ public class CategoryProvider extends FDroidProvider {
 | 
			
		||||
    @Override
 | 
			
		||||
    public Uri insert(@NonNull Uri uri, ContentValues values) {
 | 
			
		||||
        long rowId = db().insertOrThrow(getTableName(), null, values);
 | 
			
		||||
        getContext().getContentResolver().notifyChange(AppProvider.getCanUpdateUri(), null);
 | 
			
		||||
        // Don't try and notify listeners here, because it will instead happen when the TempAppProvider
 | 
			
		||||
        // is committed (when the AppProvider and ApkProviders notify their listeners). There is no
 | 
			
		||||
        // other time where categories get added (at time of writing) so this should be okay.
 | 
			
		||||
        return getCategoryIdUri(rowId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ abstract class QueryBuilder {
 | 
			
		||||
    private String selection;
 | 
			
		||||
    private String[] selectionArgs;
 | 
			
		||||
    private final List<OrderClause> orderBys = new ArrayList<>();
 | 
			
		||||
    private int limit = 0;
 | 
			
		||||
 | 
			
		||||
    protected abstract String getRequiredTables();
 | 
			
		||||
 | 
			
		||||
@ -88,6 +89,10 @@ abstract class QueryBuilder {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addLimit(int limit) {
 | 
			
		||||
        this.limit = limit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String[] getArgs() {
 | 
			
		||||
        List<String> args = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
@ -156,7 +161,11 @@ abstract class QueryBuilder {
 | 
			
		||||
        return tables.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String limitSql() {
 | 
			
		||||
        return limit > 0 ? " LIMIT " + limit : "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return "SELECT " + distinctSql() + fieldsSql() + " FROM " + tablesSql() + whereSql() + groupBySql() + orderBySql();
 | 
			
		||||
        return "SELECT " + distinctSql() + fieldsSql() + " FROM " + tablesSql() + whereSql() + groupBySql() + orderBySql() + limitSql();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -196,7 +196,7 @@ public class TempAppProvider extends AppProvider {
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return super.runQuery(uri, selection, projection, true, sortOrder);
 | 
			
		||||
        return super.runQuery(uri, selection, projection, true, sortOrder, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void ensureTempTableDetached(SQLiteDatabase db) {
 | 
			
		||||
@ -253,6 +253,7 @@ public class TempAppProvider extends AppProvider {
 | 
			
		||||
 | 
			
		||||
            getContext().getContentResolver().notifyChange(AppProvider.getContentUri(), null);
 | 
			
		||||
            getContext().getContentResolver().notifyChange(ApkProvider.getContentUri(), null);
 | 
			
		||||
            getContext().getContentResolver().notifyChange(CategoryProvider.getContentUri(), null);
 | 
			
		||||
        } finally {
 | 
			
		||||
            db.endTransaction();
 | 
			
		||||
            db.execSQL("DETACH DATABASE " + DB); // Can't be done in a transaction.
 | 
			
		||||
 | 
			
		||||
@ -185,7 +185,7 @@ public class AvailableAppsFragment extends AppListFragment implements
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri(String query) {
 | 
			
		||||
        return AppProvider.getSearchUri(query);
 | 
			
		||||
        return AppProvider.getSearchUri(query, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -109,6 +109,7 @@
 | 
			
		||||
 | 
			
		||||
    <string name="menu_update_repo">Update Repos</string>
 | 
			
		||||
    <string name="menu_manage">Repositories</string>
 | 
			
		||||
    <string name="repositories_summary">Add additional sources of applications</string>
 | 
			
		||||
    <string name="menu_send_apk_bt">Share F-Droid by Bluetooth</string>
 | 
			
		||||
    <string name="menu_settings">Settings</string>
 | 
			
		||||
    <string name="menu_about">About</string>
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <PreferenceCategory android:title="@string/updates">
 | 
			
		||||
        <PreferenceScreen
 | 
			
		||||
            android:title="@string/menu_manage"
 | 
			
		||||
            android:summary="@string/repositories_summary">
 | 
			
		||||
            <intent
 | 
			
		||||
                android:action="android.intent.action.MAIN"
 | 
			
		||||
                android:targetPackage="org.fdroid.fdroid"
 | 
			
		||||
                android:targetClass="org.fdroid.fdroid.views.ManageReposActivity" />
 | 
			
		||||
        </PreferenceScreen>
 | 
			
		||||
        <com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/update_interval"
 | 
			
		||||
            android:key="updateInterval"
 | 
			
		||||
            android:defaultValue="24"
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,33 @@ public class CategoryProviderTest extends FDroidProviderTest {
 | 
			
		||||
    //  use a separate table in the future, these should still pass.
 | 
			
		||||
    // ========================================================================
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void queryFreeTextAndCategories() {
 | 
			
		||||
        insertAppWithCategory("com.dog", "Dog", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.cat", "Cat", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.crow", "Crow", "Animal,Bird");
 | 
			
		||||
        insertAppWithCategory("com.chicken", "Chicken", "Animal,Bird,Food");
 | 
			
		||||
        insertAppWithCategory("com.dog-statue", "Dog Statue", "Animal,Mineral");
 | 
			
		||||
        insertAppWithCategory("com.rock", "Rock", "Mineral");
 | 
			
		||||
        insertAppWithCategory("com.banana", "Banana", "Food");
 | 
			
		||||
        insertAppWithCategory("com.dog-food", "Dog Food", "Food");
 | 
			
		||||
 | 
			
		||||
        assertPackagesInUri(AppProvider.getSearchUri("dog", "Animal"), new String[] {
 | 
			
		||||
                "com.dog",
 | 
			
		||||
                "com.dog-statue",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertPackagesInUri(AppProvider.getSearchUri("dog", "Food"), new String[] {
 | 
			
		||||
                "com.dog-food",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertPackagesInUri(AppProvider.getSearchUri("dog", null), new String[] {
 | 
			
		||||
                "com.dog",
 | 
			
		||||
                "com.dog-statue",
 | 
			
		||||
                "com.dog-food",
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void queryAppsInCategories() {
 | 
			
		||||
        insertAppWithCategory("com.dog", "Dog", "Animal");
 | 
			
		||||
@ -55,6 +82,13 @@ public class CategoryProviderTest extends FDroidProviderTest {
 | 
			
		||||
                "com.chicken",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertPackagesInCategory("animal", new String[] {
 | 
			
		||||
                "com.dog",
 | 
			
		||||
                "com.cat",
 | 
			
		||||
                "com.crow",
 | 
			
		||||
                "com.chicken",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertPackagesInCategory("Bird", new String[]{
 | 
			
		||||
                "com.crow",
 | 
			
		||||
                "com.chicken",
 | 
			
		||||
@ -88,6 +122,40 @@ public class CategoryProviderTest extends FDroidProviderTest {
 | 
			
		||||
        AppProviderTest.assertContainsOnlyIds(apps, expectedPackages);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void topAppsFromCategory() {
 | 
			
		||||
        insertAppWithCategory("com.dog", "Dog", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.cat", "Cat", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.bird", "Bird", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.snake", "Snake", "Animal");
 | 
			
		||||
        insertAppWithCategory("com.rat", "Rat", "Animal");
 | 
			
		||||
 | 
			
		||||
        insertAppWithCategory("com.rock", "Rock", "Mineral");
 | 
			
		||||
        insertAppWithCategory("com.stone", "Stone", "Mineral");
 | 
			
		||||
        insertAppWithCategory("com.boulder", "Boulder", "Mineral");
 | 
			
		||||
 | 
			
		||||
        insertAppWithCategory("com.banana", "Banana", "Vegetable");
 | 
			
		||||
        insertAppWithCategory("com.tomato", "Tomato", "Vegetable");
 | 
			
		||||
 | 
			
		||||
        assertContainsOnly(topAppsFromCategory("Animal", 3), new String[] {"com.bird", "com.cat", "com.dog", });
 | 
			
		||||
        assertContainsOnly(topAppsFromCategory("Animal", 2), new String[] {"com.bird", "com.cat", });
 | 
			
		||||
        assertContainsOnly(topAppsFromCategory("Animal", 1), new String[] {"com.bird", });
 | 
			
		||||
 | 
			
		||||
        assertContainsOnly(topAppsFromCategory("Mineral", 2), new String[] {"com.boulder", "com.rock", });
 | 
			
		||||
 | 
			
		||||
        assertContainsOnly(topAppsFromCategory("Vegetable", 10), new String[] {"com.banana", "com.tomato", });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String[] topAppsFromCategory(String category, int numToGet) {
 | 
			
		||||
        List<App> apps = AppProvider.Helper.cursorToList(contentResolver.query(AppProvider.getTopFromCategoryUri(category, numToGet), Cols.ALL, null, null, Cols.NAME));
 | 
			
		||||
        String[] packageNames = new String[apps.size()];
 | 
			
		||||
        for (int i = 0; i < apps.size(); i++) {
 | 
			
		||||
            packageNames[i] = apps.get(i).packageName;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return packageNames;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCategoriesSingle() {
 | 
			
		||||
        insertAppWithCategory("com.dog", "Dog", "Animal");
 | 
			
		||||
 | 
			
		||||
@ -84,10 +84,15 @@ public class ProviderUriTests {
 | 
			
		||||
        ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
 | 
			
		||||
        String[] projection = new String[] {Schema.AppMetadataTable.Cols._ID};
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getContentUri(), "content://org.fdroid.fdroid.data.AppProvider", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("'searching!'"), "content://org.fdroid.fdroid.data.AppProvider/search/'searching!'", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("/"), "content://org.fdroid.fdroid.data.AppProvider/search/%2F", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri(""), "content://org.fdroid.fdroid.data.AppProvider", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri(null), "content://org.fdroid.fdroid.data.AppProvider", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("'searching!'", null), "content://org.fdroid.fdroid.data.AppProvider/search/'searching!'", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("'searching!'", "Games"), "content://org.fdroid.fdroid.data.AppProvider/search/'searching!'/Games", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("/", null), "content://org.fdroid.fdroid.data.AppProvider/search/%2F", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("/", "Games"), "content://org.fdroid.fdroid.data.AppProvider/search/%2F/Games", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("", null), "content://org.fdroid.fdroid.data.AppProvider", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getCategoryUri("Games"), "content://org.fdroid.fdroid.data.AppProvider/category/Games", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri("", "Games"), "content://org.fdroid.fdroid.data.AppProvider/category/Games", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri((String) null, null), "content://org.fdroid.fdroid.data.AppProvider", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getSearchUri((String) null, "Games"), "content://org.fdroid.fdroid.data.AppProvider/category/Games", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getInstalledUri(), "content://org.fdroid.fdroid.data.AppProvider/installed", projection);
 | 
			
		||||
        assertValidUri(resolver, AppProvider.getCanUpdateUri(), "content://org.fdroid.fdroid.data.AppProvider/canUpdate", projection);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user