Calculate whether an app is an APK or not when updating repos.
This improves performance when we need to decide whether or not apps are installed or not while scrolling through large lists. Fixes #1143. Also change Jackson tests to properly ignore App#isApk.
This commit is contained in:
parent
ac1dce24d2
commit
595f72d5b2
@ -226,6 +226,12 @@ public class IndexV1Updater extends RepoUpdater {
|
|||||||
|
|
||||||
if (apks.size() > 0) {
|
if (apks.size() > 0) {
|
||||||
app.preferredSigner = apks.get(0).sig;
|
app.preferredSigner = apks.get(0).sig;
|
||||||
|
app.isApk = true;
|
||||||
|
for (Apk apk : apks) {
|
||||||
|
if (!apk.isApk()) {
|
||||||
|
app.isApk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appCount % 50 == 0) {
|
if (appCount % 50 == 0) {
|
||||||
|
@ -104,6 +104,8 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@NonNull
|
@NonNull
|
||||||
public String preferredSigner;
|
public String preferredSigner;
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isApk;
|
||||||
|
|
||||||
@JacksonInject("repoId")
|
@JacksonInject("repoId")
|
||||||
public long repoId;
|
public long repoId;
|
||||||
@ -347,6 +349,9 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
case Cols.WEAR_SCREENSHOTS:
|
case Cols.WEAR_SCREENSHOTS:
|
||||||
wearScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
wearScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
break;
|
break;
|
||||||
|
case Cols.IS_APK:
|
||||||
|
isApk = cursor.getInt(i) == 1;
|
||||||
|
break;
|
||||||
case Cols.InstalledApp.VERSION_CODE:
|
case Cols.InstalledApp.VERSION_CODE:
|
||||||
installedVersionCode = cursor.getInt(i);
|
installedVersionCode = cursor.getInt(i);
|
||||||
break;
|
break;
|
||||||
@ -854,12 +859,19 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
values.put(Cols.TV_SCREENSHOTS, Utils.serializeCommaSeparatedString(tvScreenshots));
|
values.put(Cols.TV_SCREENSHOTS, Utils.serializeCommaSeparatedString(tvScreenshots));
|
||||||
values.put(Cols.WEAR_SCREENSHOTS, Utils.serializeCommaSeparatedString(wearScreenshots));
|
values.put(Cols.WEAR_SCREENSHOTS, Utils.serializeCommaSeparatedString(wearScreenshots));
|
||||||
values.put(Cols.IS_COMPATIBLE, compatible ? 1 : 0);
|
values.put(Cols.IS_COMPATIBLE, compatible ? 1 : 0);
|
||||||
|
values.put(Cols.IS_APK, isApk ? 1 : 0);
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstalled(Context context) {
|
public boolean isInstalled(Context context) {
|
||||||
return installedVersionCode > 0 || isMediaInstalled(context);
|
// First check isApk() before isMediaInstalled() because the latter is quite expensive,
|
||||||
|
// hitting the database for each apk version, then the disk to check for installed media.
|
||||||
|
return installedVersionCode > 0 || (!isApk() && isMediaInstalled(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isApk() {
|
||||||
|
return isApk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMediaInstalled(Context context) {
|
public boolean isMediaInstalled(Context context) {
|
||||||
@ -1064,6 +1076,7 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
dest.writeStringArray(this.tenInchScreenshots);
|
dest.writeStringArray(this.tenInchScreenshots);
|
||||||
dest.writeStringArray(this.tvScreenshots);
|
dest.writeStringArray(this.tvScreenshots);
|
||||||
dest.writeStringArray(this.wearScreenshots);
|
dest.writeStringArray(this.wearScreenshots);
|
||||||
|
dest.writeByte(this.isApk ? (byte) 1 : (byte) 0);
|
||||||
dest.writeString(this.installedVersionName);
|
dest.writeString(this.installedVersionName);
|
||||||
dest.writeInt(this.installedVersionCode);
|
dest.writeInt(this.installedVersionCode);
|
||||||
dest.writeParcelable(this.installedApk, flags);
|
dest.writeParcelable(this.installedApk, flags);
|
||||||
@ -1114,6 +1127,7 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
this.tenInchScreenshots = in.createStringArray();
|
this.tenInchScreenshots = in.createStringArray();
|
||||||
this.tvScreenshots = in.createStringArray();
|
this.tvScreenshots = in.createStringArray();
|
||||||
this.wearScreenshots = in.createStringArray();
|
this.wearScreenshots = in.createStringArray();
|
||||||
|
this.isApk = in.readByte() != 0;
|
||||||
this.installedVersionName = in.readString();
|
this.installedVersionName = in.readString();
|
||||||
this.installedVersionCode = in.readInt();
|
this.installedVersionCode = in.readInt();
|
||||||
this.installedApk = in.readParcelable(Apk.class.getClassLoader());
|
this.installedApk = in.readParcelable(Apk.class.getClassLoader());
|
||||||
|
@ -151,6 +151,7 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
+ AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS + " string,"
|
+ AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS + " string,"
|
||||||
+ AppMetadataTable.Cols.TV_SCREENSHOTS + " string,"
|
+ AppMetadataTable.Cols.TV_SCREENSHOTS + " string,"
|
||||||
+ AppMetadataTable.Cols.WEAR_SCREENSHOTS + " string,"
|
+ AppMetadataTable.Cols.WEAR_SCREENSHOTS + " string,"
|
||||||
|
+ AppMetadataTable.Cols.IS_APK + " boolean,"
|
||||||
+ "primary key(" + AppMetadataTable.Cols.PACKAGE_ID + ", " + AppMetadataTable.Cols.REPO_ID + "));";
|
+ "primary key(" + AppMetadataTable.Cols.PACKAGE_ID + ", " + AppMetadataTable.Cols.REPO_ID + "));";
|
||||||
|
|
||||||
private static final String CREATE_TABLE_APP_PREFS = "CREATE TABLE " + AppPrefsTable.NAME
|
private static final String CREATE_TABLE_APP_PREFS = "CREATE TABLE " + AppPrefsTable.NAME
|
||||||
@ -193,7 +194,7 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
+ InstalledAppTable.Cols.HASH + " TEXT NOT NULL"
|
+ InstalledAppTable.Cols.HASH + " TEXT NOT NULL"
|
||||||
+ " );";
|
+ " );";
|
||||||
|
|
||||||
protected static final int DB_VERSION = 73;
|
protected static final int DB_VERSION = 74;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
@ -281,6 +282,30 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
addIntegerPrimaryKeyToInstalledApps(db, oldVersion);
|
addIntegerPrimaryKeyToInstalledApps(db, oldVersion);
|
||||||
addPreferredSignerToApp(db, oldVersion);
|
addPreferredSignerToApp(db, oldVersion);
|
||||||
updatePreferredSignerIfEmpty(db, oldVersion);
|
updatePreferredSignerIfEmpty(db, oldVersion);
|
||||||
|
addIsAppToApp(db, oldVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addIsAppToApp(SQLiteDatabase db, int oldVersion) {
|
||||||
|
if (oldVersion >= 74) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.IS_APK)) {
|
||||||
|
Log.i(TAG, "Figuring out whether each \"app\" is actually an app, or it represents other media.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.IS_APK + " boolean;");
|
||||||
|
|
||||||
|
// Find all apks for which their filename DOESN'T end in ".apk", and if there is more than one, the
|
||||||
|
// corresponding app is updated to be marked as media.
|
||||||
|
String apkName = ApkTable.Cols.NAME;
|
||||||
|
String query = "UPDATE " + AppMetadataTable.NAME + " SET " + AppMetadataTable.Cols.IS_APK + " = (" +
|
||||||
|
" SELECT COUNT(*) FROM " + ApkTable.NAME + " AS apk" +
|
||||||
|
" WHERE " +
|
||||||
|
" " + ApkTable.Cols.APP_ID + " = " + AppMetadataTable.NAME + "." + AppMetadataTable.Cols.ROW_ID +
|
||||||
|
" AND SUBSTR(" + apkName + ", LENGTH(" + apkName + ") - 3) != '.apk'" +
|
||||||
|
") = 0;";
|
||||||
|
Log.i(TAG, query);
|
||||||
|
db.execSQL(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePreferredSignerIfEmpty(SQLiteDatabase db, int oldVersion) {
|
private void updatePreferredSignerIfEmpty(SQLiteDatabase db, int oldVersion) {
|
||||||
|
@ -156,6 +156,7 @@ public interface Schema {
|
|||||||
String TEN_INCH_SCREENSHOTS = "tenInchScreenshots";
|
String TEN_INCH_SCREENSHOTS = "tenInchScreenshots";
|
||||||
String TV_SCREENSHOTS = "tvScreenshots";
|
String TV_SCREENSHOTS = "tvScreenshots";
|
||||||
String WEAR_SCREENSHOTS = "wearScreenshots";
|
String WEAR_SCREENSHOTS = "wearScreenshots";
|
||||||
|
String IS_APK = "isApk";
|
||||||
|
|
||||||
interface SuggestedApk {
|
interface SuggestedApk {
|
||||||
String VERSION_NAME = "suggestedApkVersion";
|
String VERSION_NAME = "suggestedApkVersion";
|
||||||
@ -195,7 +196,7 @@ public interface Schema {
|
|||||||
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
||||||
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
||||||
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
||||||
PREFERRED_SIGNER, SUGGESTED_VERSION_CODE,
|
PREFERRED_SIGNER, SUGGESTED_VERSION_CODE, IS_APK,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,7 +212,7 @@ public interface Schema {
|
|||||||
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
||||||
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
||||||
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
||||||
PREFERRED_SIGNER, SUGGESTED_VERSION_CODE, SuggestedApk.VERSION_NAME,
|
PREFERRED_SIGNER, SUGGESTED_VERSION_CODE, IS_APK, SuggestedApk.VERSION_NAME,
|
||||||
InstalledApp.VERSION_CODE, InstalledApp.VERSION_NAME,
|
InstalledApp.VERSION_CODE, InstalledApp.VERSION_NAME,
|
||||||
InstalledApp.SIGNATURE, Package.PACKAGE_NAME,
|
InstalledApp.SIGNATURE, Package.PACKAGE_NAME,
|
||||||
};
|
};
|
||||||
|
@ -304,6 +304,7 @@ public class IndexV1UpdaterTest extends FDroidProviderTest {
|
|||||||
"installedSig",
|
"installedSig",
|
||||||
"installedVersionCode",
|
"installedVersionCode",
|
||||||
"installedVersionName",
|
"installedVersionName",
|
||||||
|
"isApk",
|
||||||
"preferredSigner",
|
"preferredSigner",
|
||||||
"prefs",
|
"prefs",
|
||||||
"TAG",
|
"TAG",
|
||||||
@ -335,6 +336,7 @@ public class IndexV1UpdaterTest extends FDroidProviderTest {
|
|||||||
"hash",
|
"hash",
|
||||||
"hashType",
|
"hashType",
|
||||||
"incompatibleReasons",
|
"incompatibleReasons",
|
||||||
|
"isApk",
|
||||||
"maxSdkVersion",
|
"maxSdkVersion",
|
||||||
"minSdkVersion",
|
"minSdkVersion",
|
||||||
"nativecode",
|
"nativecode",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user