From 4895e2d790ec3b91fa4271a24e1ea0ae69d362f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Tue, 9 Jun 2015 17:44:18 +0200 Subject: [PATCH] Fix large icons by caching two icon urls per app in the DB --- F-Droid/src/org/fdroid/fdroid/AppDetails.java | 10 +- F-Droid/src/org/fdroid/fdroid/Utils.java | 8 ++ F-Droid/src/org/fdroid/fdroid/data/App.java | 7 ++ .../org/fdroid/fdroid/data/AppProvider.java | 102 ++++++++++-------- .../src/org/fdroid/fdroid/data/DBHelper.java | 17 ++- 5 files changed, 89 insertions(+), 55 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/AppDetails.java b/F-Droid/src/org/fdroid/fdroid/AppDetails.java index 15513d7c5..8f5d09e84 100644 --- a/F-Droid/src/org/fdroid/fdroid/AppDetails.java +++ b/F-Droid/src/org/fdroid/fdroid/AppDetails.java @@ -363,10 +363,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A fdroidApp = ((FDroidApp) getApplication()); fdroidApp.applyTheme(this); - /* TODO: - AppProvider.updateIconUrls(1.5); - */ - super.onCreate(savedInstanceState); // Must be called *after* super.onCreate(), as that is where the action bar @@ -553,9 +549,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } } inProcessOfChangingConfiguration = false; - /* TODO - AppProvider.updateIconUrls(1.0); - */ super.onDestroy(); } @@ -1492,7 +1485,8 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A // Set the icon... ImageView iv = (ImageView) view.findViewById(R.id.icon); - ImageLoader.getInstance().displayImage(getApp().iconUrl, iv, displayImageOptions); + ImageLoader.getInstance().displayImage(getApp().iconUrlLarge, iv, + displayImageOptions); // Set the title TextView tv = (TextView) view.findViewById(R.id.title); diff --git a/F-Droid/src/org/fdroid/fdroid/Utils.java b/F-Droid/src/org/fdroid/fdroid/Utils.java index 1275d0d4e..3966d294a 100644 --- a/F-Droid/src/org/fdroid/fdroid/Utils.java +++ b/F-Droid/src/org/fdroid/fdroid/Utils.java @@ -79,6 +79,14 @@ public final class Utils { private static final SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH); + public static final String FALLBACK_ICONS_DIR = "/icons/"; + + /* + * @param dpiMultiplier Lets you grab icons for densities larger or + * smaller than that of your device by some fraction. Useful, for example, + * if you want to display a 48dp image at twice the size, 96dp, in which + * case you'd use a dpiMultiplier of 2.0 to get an image twice as big. + */ public static String getIconsDir(final Context context, final double dpiMultiplier) { final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); final double dpi = metrics.densityDpi * dpiMultiplier; diff --git a/F-Droid/src/org/fdroid/fdroid/data/App.java b/F-Droid/src/org/fdroid/fdroid/data/App.java index 2be638cc1..985dd749f 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/App.java +++ b/F-Droid/src/org/fdroid/fdroid/data/App.java @@ -91,7 +91,10 @@ public class App extends ValueObject implements Comparable { // True if the current update for this app is to be ignored public int ignoreThisUpdate; + // To be displayed at 48dp (x1.0) public String iconUrl; + // To be displayed at 72dp (x1.5) + public String iconUrlLarge; public String installedVersionName; @@ -196,6 +199,9 @@ public class App extends ValueObject implements Comparable { case AppProvider.DataColumns.ICON_URL: iconUrl = cursor.getString(i); break; + case AppProvider.DataColumns.ICON_URL_LARGE: + iconUrlLarge = cursor.getString(i); + break; case AppProvider.DataColumns.InstalledApp.VERSION_CODE: installedVersionCode = cursor.getInt(i); break; @@ -355,6 +361,7 @@ public class App extends ValueObject implements Comparable { values.put(AppProvider.DataColumns.SUMMARY, summary); values.put(AppProvider.DataColumns.ICON, icon); values.put(AppProvider.DataColumns.ICON_URL, iconUrl); + values.put(AppProvider.DataColumns.ICON_URL_LARGE, iconUrlLarge); values.put(AppProvider.DataColumns.DESCRIPTION, description); values.put(AppProvider.DataColumns.LICENSE, license); values.put(AppProvider.DataColumns.WEB_URL, webURL); diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index 652328132..7c223e3b5 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -183,6 +183,7 @@ public class AppProvider extends FDroidProvider { String IGNORE_ALLUPDATES = "ignoreAllUpdates"; String IGNORE_THISUPDATE = "ignoreThisUpdate"; String ICON_URL = "iconUrl"; + String ICON_URL_LARGE = "iconUrlLarge"; interface SuggestedApk { String VERSION = "suggestedApkVersion"; @@ -199,9 +200,9 @@ public class AppProvider extends FDroidProvider { BITCOIN_ADDR, LITECOIN_ADDR, DOGECOIN_ADDR, FLATTR_ID, UPSTREAM_VERSION, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED, CATEGORIES, ANTI_FEATURES, REQUIREMENTS, IGNORE_ALLUPDATES, - IGNORE_THISUPDATE, ICON_URL, SUGGESTED_VERSION_CODE, - SuggestedApk.VERSION, InstalledApp.VERSION_CODE, - InstalledApp.VERSION_NAME + IGNORE_THISUPDATE, ICON_URL, ICON_URL_LARGE, + SUGGESTED_VERSION_CODE, SuggestedApk.VERSION, + InstalledApp.VERSION_CODE, InstalledApp.VERSION_NAME }; } @@ -789,7 +790,7 @@ public class AppProvider extends FDroidProvider { updateCompatibleFlags(); updateSuggestedFromLatest(); updateSuggestedFromUpstream(); - updateIconUrls(1.0); + updateIconUrls(); } /** @@ -923,16 +924,19 @@ public class AppProvider extends FDroidProvider { /** * Updates URLs to icons - * - * @param dpiMultiplier Lets you grab icons for densities larger or smaller than that of your device by some fraction. Useful, for example, if you want to display a 48dp image at twice the size, 96dp, in which case you'd use a dpiMultiplier of 2.0 to get an image twice as big. */ - public void updateIconUrls(final double dpiMultiplier) { - Log.d(TAG, "Updating icon paths for apps belonging to repos with version >= " + Repo.VERSION_DENSITY_SPECIFIC_ICONS); - final String iconsDir = Utils.getIconsDir(getContext(), dpiMultiplier); - Log.d(TAG, "Using icon dir '"+iconsDir+"'"); + public void updateIconUrls() { + final String iconsDir = Utils.getIconsDir(getContext(), 1.0); + final String iconsDirLarge = Utils.getIconsDir(getContext(), 1.5); String repoVersion = Integer.toString(Repo.VERSION_DENSITY_SPECIFIC_ICONS); + Log.d(TAG, "Updating icon paths for apps belonging to repos with version >= " + + repoVersion); + Log.d(TAG, "Using icons dir '" + iconsDir + "'"); + Log.d(TAG, "Using large icons dir '" + iconsDirLarge + "'"); String query = getIconUpdateQuery(); - final String[] params = { repoVersion, iconsDir }; + final String[] params = { + repoVersion, iconsDir, Utils.FALLBACK_ICONS_DIR, + repoVersion, iconsDirLarge, Utils.FALLBACK_ICONS_DIR }; write().execSQL(query, params); } @@ -947,39 +951,51 @@ public class AppProvider extends FDroidProvider { final String app = DBHelper.TABLE_APP; final String repo = DBHelper.TABLE_REPO; + final String iconUrlQuery = + " SELECT " + + + // Concatenate (using the "||" operator) the address, the + // icons directory (bound to the ? as the second parameter + // when executing the query) and the icon path. + " ( " + + repo + ".address " + + " || " + + + // If the repo has the relevant version, then use a more + // intelligent icons dir, otherwise revert to the default + // one + " CASE WHEN " + repo + ".version >= ? THEN ? ELSE ? END " + + + " || " + + app + ".icon " + + ") " + + " FROM " + + apk + + " JOIN " + repo + " ON (" + repo + "._id = " + apk + ".repo) " + + " WHERE " + + app + ".id = " + apk + ".id AND " + + apk + ".vercode = ( " + + + // We only want the latest apk here. Ideally, we should + // instead join onto apk.suggestedVercode, but as per + // https://gitlab.com/fdroid/fdroidclient/issues/1 there + // may be some situations where suggestedVercode isn't + // set. + // TODO: If we can guarantee that suggestedVercode is set, + // then join onto that instead. This will save from doing + // a futher sub query for each app. + " SELECT MAX(inner_apk.vercode) " + + " FROM fdroid_apk as inner_apk " + + " WHERE inner_apk.id = fdroid_apk.id ) " + + " AND fdroid_apk.repo = fdroid_repo._id "; + return - " UPDATE " + app + " SET iconUrl = ( " + - " SELECT " + - - // Concatenate (using the "||" operator) the address, the icons directory (bound to the ? as the - // second parameter when executing the query) and the icon path. - " ( " + - repo + ".address " + - " || " + - - // If the repo has the relevant version, then use a more intelligent icons dir, - // otherwise revert to '/icons/' - " CASE WHEN " + repo + ".version >= ? THEN ? ELSE '/icons/' END " + - - " || " + - app + ".icon " + - ") " + - " FROM " + - apk + - " JOIN " + repo + " ON (" + repo + "._id = " + apk + ".repo) " + - " WHERE " + - app + ".id = " + apk + ".id AND " + - apk + ".vercode = ( " + - - // We only want the latest apk here. Ideally, we should instead join - // onto apk.suggestedVercode, but as per https://gitlab.com/fdroid/fdroidclient/issues/1 - // there may be some situations where suggestedVercode isn't set. - // TODO: If we can guarantee that suggestedVercode is set, then join onto that instead. - // This will save from doing a futher sub query for each app. - " SELECT MAX(inner_apk.vercode) " + - " FROM fdroid_apk as inner_apk " + - " WHERE inner_apk.id = fdroid_apk.id ) " + - " AND fdroid_apk.repo = fdroid_repo._id " + + " UPDATE " + app + " SET " + + " iconUrl = ( " + + iconUrlQuery + + " ), " + + " iconUrlLarge = ( " + + iconUrlQuery + " ) "; } diff --git a/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java b/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java index 2fe5adf77..86b8f363f 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java +++ b/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java @@ -89,6 +89,7 @@ public class DBHelper extends SQLiteOpenHelper { + "ignoreAllUpdates int not null," + "ignoreThisUpdate int not null," + "iconUrl text, " + + "iconUrlLarge text, " + "primary key(id));"; public static final String TABLE_INSTALLED_APP = "fdroid_installedApp"; @@ -100,7 +101,7 @@ public class DBHelper extends SQLiteOpenHelper { + InstalledAppProvider.DataColumns.APPLICATION_LABEL + " TEXT NOT NULL " + " );"; - private static final int DB_VERSION = 48; + private static final int DB_VERSION = 49; private final Context context; @@ -281,7 +282,8 @@ public class DBHelper extends SQLiteOpenHelper { if (oldVersion < 43) createInstalledApp(db); addAppLabelToInstalledCache(db, oldVersion); addIsSwapToRepo(db, oldVersion); - addChangelogToRepo(db, oldVersion); + addChangelogToApp(db, oldVersion); + addIconUrlLargeToApp(db, oldVersion); } /** @@ -416,10 +418,17 @@ public class DBHelper extends SQLiteOpenHelper { } } - private void addChangelogToRepo(SQLiteDatabase db, int oldVersion) { + private void addChangelogToApp(SQLiteDatabase db, int oldVersion) { if (oldVersion < 48 && !columnExists(db, TABLE_APP, "changelogURL")) { Log.i(TAG, "Adding changelogURL column to " + TABLE_APP); - db.execSQL("Alter table " + TABLE_APP + " add column changelogURL text"); + db.execSQL("alter table " + TABLE_APP + " add column changelogURL text"); + } + } + + private void addIconUrlLargeToApp(SQLiteDatabase db, int oldVersion) { + if (oldVersion < 49 && !columnExists(db, TABLE_APP, "iconUrlLarge")) { + Log.i(TAG, "Adding iconUrlLarge columns to " + TABLE_APP); + db.execSQL("alter table " + TABLE_APP + " add column iconUrlLarge text"); } }