support localized text and graphics in index-v1 metadata
This sets the App instance variables using the localized index-v1 fields. It trys to fill as many fields as possible, falling back to locales of the same language, then finally English. This is based on the Jackson JSON parser's ability to map a JSON key to a method, e.g. @JsonProperty("localized")
This commit is contained in:
parent
d769dcfc60
commit
9d97546c4f
@ -136,10 +136,11 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
// Load the feature graphic, if present
|
// Load the feature graphic, if present
|
||||||
if (!TextUtils.isEmpty(app.iconUrl)) {
|
String featureGraphicUrl = app.getFeatureGraphicUrl(this);
|
||||||
|
if (!TextUtils.isEmpty(featureGraphicUrl)) {
|
||||||
final FeatureImage featureImage = (FeatureImage) findViewById(R.id.feature_graphic);
|
final FeatureImage featureImage = (FeatureImage) findViewById(R.id.feature_graphic);
|
||||||
DisplayImageOptions displayImageOptions = Utils.getImageLoadingOptions().build();
|
DisplayImageOptions displayImageOptions = Utils.getImageLoadingOptions().build();
|
||||||
ImageLoader.getInstance().loadImage(app.iconUrl, displayImageOptions, new ImageLoadingListener() {
|
ImageLoader.getInstance().loadImage(featureGraphicUrl, displayImageOptions, new ImageLoadingListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||||
if (featureImage != null) {
|
if (featureImage != null) {
|
||||||
|
@ -17,6 +17,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import org.apache.commons.io.filefilter.RegexFileFilter;
|
import org.apache.commons.io.filefilter.RegexFileFilter;
|
||||||
import org.fdroid.fdroid.AppFilter;
|
import org.fdroid.fdroid.AppFilter;
|
||||||
@ -32,10 +33,16 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -73,6 +80,7 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
* At most other times, we don't particularly care which repo an {@link App} object came from.
|
* At most other times, we don't particularly care which repo an {@link App} object came from.
|
||||||
* It is pretty much transparent, because the metadata will be populated from the repo with
|
* It is pretty much transparent, because the metadata will be populated from the repo with
|
||||||
* the highest priority. The UI doesn't care normally _which_ repo provided the metadata.
|
* the highest priority. The UI doesn't care normally _which_ repo provided the metadata.
|
||||||
|
* This is required for getting the full URL to the various graphics and screenshots.
|
||||||
*/
|
*/
|
||||||
public long repoId;
|
public long repoId;
|
||||||
public String summary = "Unknown application";
|
public String summary = "Unknown application";
|
||||||
@ -80,6 +88,18 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
|
|
||||||
public String description;
|
public String description;
|
||||||
|
|
||||||
|
public String video;
|
||||||
|
|
||||||
|
public String featureGraphic;
|
||||||
|
public String promoGraphic;
|
||||||
|
public String tvBanner;
|
||||||
|
|
||||||
|
public String[] phoneScreenshots = new String[0];
|
||||||
|
public String[] sevenInchScreenshots = new String[0];
|
||||||
|
public String[] tenInchScreenshots = new String[0];
|
||||||
|
public String[] tvScreenshots = new String[0];
|
||||||
|
public String[] wearScreenshots = new String[0];
|
||||||
|
|
||||||
public String license = "Unknown";
|
public String license = "Unknown";
|
||||||
|
|
||||||
public String authorName;
|
public String authorName;
|
||||||
@ -263,6 +283,30 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
case Cols.ICON_URL_LARGE:
|
case Cols.ICON_URL_LARGE:
|
||||||
iconUrlLarge = cursor.getString(i);
|
iconUrlLarge = cursor.getString(i);
|
||||||
break;
|
break;
|
||||||
|
case Cols.FEATURE_GRAPHIC:
|
||||||
|
featureGraphic = cursor.getString(i);
|
||||||
|
break;
|
||||||
|
case Cols.PROMO_GRAPHIC:
|
||||||
|
promoGraphic = cursor.getString(i);
|
||||||
|
break;
|
||||||
|
case Cols.TV_BANNER:
|
||||||
|
tvBanner = cursor.getString(i);
|
||||||
|
break;
|
||||||
|
case Cols.PHONE_SCREENSHOTS:
|
||||||
|
phoneScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
|
break;
|
||||||
|
case Cols.SEVEN_INCH_SCREENSHOTS:
|
||||||
|
sevenInchScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
|
break;
|
||||||
|
case Cols.TEN_INCH_SCREENSHOTS:
|
||||||
|
tenInchScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
|
break;
|
||||||
|
case Cols.TV_SCREENSHOTS:
|
||||||
|
tvScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
|
break;
|
||||||
|
case Cols.WEAR_SCREENSHOTS:
|
||||||
|
wearScreenshots = Utils.parseCommaSeparatedString(cursor.getString(i));
|
||||||
|
break;
|
||||||
case Cols.InstalledApp.VERSION_CODE:
|
case Cols.InstalledApp.VERSION_CODE:
|
||||||
installedVersionCode = cursor.getInt(i);
|
installedVersionCode = cursor.getInt(i);
|
||||||
break;
|
break;
|
||||||
@ -293,6 +337,175 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
initApkFromApkFile(context, this.installedApk, packageInfo, apkFile);
|
initApkFromApkFile(context, this.installedApk, packageInfo, apkFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the {@code localized} block in the incoming index metadata,
|
||||||
|
* choosing the best match in terms of locale/language while filling as
|
||||||
|
* many fields as possible. The first English locale found is loaded, then
|
||||||
|
* {@code en-US} is loaded over that, since that's the most common English
|
||||||
|
* for software. Then the first language match, and then finally the
|
||||||
|
* current locale for this device, given it precedence over all the others.
|
||||||
|
* <p>
|
||||||
|
* It is still possible that the fields will be loaded directly without any
|
||||||
|
* locale info. This comes from the old-style {@code .txt} app metadata
|
||||||
|
* fields that do not have locale info. They should not be used if the
|
||||||
|
* {@code Localized} block is specified.
|
||||||
|
*/
|
||||||
|
@JsonProperty("localized")
|
||||||
|
private void setLocalized(Map<String, Map<String, Object>> localized) { // NOPMD
|
||||||
|
Locale defaultLocale = Locale.getDefault();
|
||||||
|
String languageTag = defaultLocale.getLanguage();
|
||||||
|
String localeTag = languageTag + "-" + defaultLocale.getCountry();
|
||||||
|
Set<String> locales = localized.keySet();
|
||||||
|
Set<String> localesToUse = new TreeSet<>();
|
||||||
|
|
||||||
|
if (locales.contains(localeTag)) {
|
||||||
|
localesToUse.add(localeTag);
|
||||||
|
}
|
||||||
|
for (String l : locales) {
|
||||||
|
if (l.startsWith(languageTag)) {
|
||||||
|
localesToUse.add(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (locales.contains("en-US")) {
|
||||||
|
localesToUse.add("en-US");
|
||||||
|
}
|
||||||
|
for (String l : locales) {
|
||||||
|
if (l.startsWith("en")) {
|
||||||
|
localesToUse.add(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if key starts with Upper case, its set by humans
|
||||||
|
// Name, Summary, Description existed before localization so their values can be set directly
|
||||||
|
video = getLocalizedEntry(localized, localesToUse, "Video");
|
||||||
|
String value = getLocalizedEntry(localized, localesToUse, "Name");
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
name = value;
|
||||||
|
}
|
||||||
|
value = getLocalizedEntry(localized, localesToUse, "Summary");
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
summary = value;
|
||||||
|
}
|
||||||
|
description = getLocalizedEntry(localized, localesToUse, "Description");
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
description = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if key starts with lower case, its generated based on finding the files
|
||||||
|
featureGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "featureGraphic");
|
||||||
|
promoGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "promoGraphic");
|
||||||
|
tvBanner = getLocalizedGraphicsEntry(localized, localesToUse, "tvBanner");
|
||||||
|
|
||||||
|
wearScreenshots = setLocalizedListEntry(localized, localesToUse, "wearScreenshots");
|
||||||
|
phoneScreenshots = setLocalizedListEntry(localized, localesToUse, "phoneScreenshots");
|
||||||
|
sevenInchScreenshots = setLocalizedListEntry(localized, localesToUse, "sevenInchScreenshots");
|
||||||
|
tenInchScreenshots = setLocalizedListEntry(localized, localesToUse, "tenInchScreenshots");
|
||||||
|
tvScreenshots = setLocalizedListEntry(localized, localesToUse, "tvScreenshots");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLocalizedEntry(Map<String, Map<String, Object>> localized,
|
||||||
|
Set<String> locales, String key) {
|
||||||
|
try {
|
||||||
|
for (String locale : locales) {
|
||||||
|
if (localized.containsKey(locale)) {
|
||||||
|
return (String) localized.get(locale).get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
Utils.debugLog(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLocalizedGraphicsEntry(Map<String, Map<String, Object>> localized,
|
||||||
|
Set<String> locales, String key) {
|
||||||
|
try {
|
||||||
|
for (String locale : locales) {
|
||||||
|
if (localized.containsKey(locale)) {
|
||||||
|
return locale + "/" + localized.get(locale).get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
Utils.debugLog(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] setLocalizedListEntry(Map<String, Map<String, Object>> localized,
|
||||||
|
Set<String> locales, String key) {
|
||||||
|
try {
|
||||||
|
for (String locale : locales) {
|
||||||
|
if (localized.containsKey(locale)) {
|
||||||
|
ArrayList<String> entry = (ArrayList<String>) localized.get(locale).get(key);
|
||||||
|
if (entry != null && entry.size() > 0) {
|
||||||
|
String[] result = new String[entry.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (String e : entry) {
|
||||||
|
result[i] = locale + "/" + key + "/" + e;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
Utils.debugLog(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFeatureGraphicUrl(Context context) {
|
||||||
|
if (TextUtils.isEmpty(featureGraphic)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Repo repo = RepoProvider.Helper.findById(context, repoId);
|
||||||
|
return repo.address + "/" + packageName + "/" + featureGraphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPromoGraphic(Context context) {
|
||||||
|
if (TextUtils.isEmpty(promoGraphic)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Repo repo = RepoProvider.Helper.findById(context, repoId);
|
||||||
|
return repo.address + "/" + packageName + "/" + promoGraphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTvBanner(Context context) {
|
||||||
|
if (TextUtils.isEmpty(tvBanner)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Repo repo = RepoProvider.Helper.findById(context, repoId);
|
||||||
|
return repo.address + "/" + packageName + "/" + tvBanner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getAllScreenshots(Context context) {
|
||||||
|
Repo repo = RepoProvider.Helper.findById(context, repoId);
|
||||||
|
ArrayList<String> list = new ArrayList<>();
|
||||||
|
if (phoneScreenshots != null) {
|
||||||
|
Collections.addAll(list, phoneScreenshots);
|
||||||
|
}
|
||||||
|
if (sevenInchScreenshots != null) {
|
||||||
|
Collections.addAll(list, sevenInchScreenshots);
|
||||||
|
}
|
||||||
|
if (tenInchScreenshots != null) {
|
||||||
|
Collections.addAll(list, tenInchScreenshots);
|
||||||
|
}
|
||||||
|
if (tvScreenshots != null) {
|
||||||
|
Collections.addAll(list, tvScreenshots);
|
||||||
|
}
|
||||||
|
if (wearScreenshots != null) {
|
||||||
|
Collections.addAll(list, wearScreenshots);
|
||||||
|
}
|
||||||
|
String[] result = new String[list.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (String url : list) {
|
||||||
|
result[i] = repo.address + "/" + packageName + "/" + url;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the directory where APK Expansion Files aka OBB files are stored for the app as
|
* Get the directory where APK Expansion Files aka OBB files are stored for the app as
|
||||||
* specified by {@code packageName}.
|
* specified by {@code packageName}.
|
||||||
@ -525,6 +738,14 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
values.put(Cols.ForWriting.Categories.CATEGORIES, Utils.serializeCommaSeparatedString(categories));
|
values.put(Cols.ForWriting.Categories.CATEGORIES, Utils.serializeCommaSeparatedString(categories));
|
||||||
values.put(Cols.ANTI_FEATURES, Utils.serializeCommaSeparatedString(antiFeatures));
|
values.put(Cols.ANTI_FEATURES, Utils.serializeCommaSeparatedString(antiFeatures));
|
||||||
values.put(Cols.REQUIREMENTS, Utils.serializeCommaSeparatedString(requirements));
|
values.put(Cols.REQUIREMENTS, Utils.serializeCommaSeparatedString(requirements));
|
||||||
|
values.put(Cols.FEATURE_GRAPHIC, featureGraphic);
|
||||||
|
values.put(Cols.PROMO_GRAPHIC, promoGraphic);
|
||||||
|
values.put(Cols.TV_BANNER, tvBanner);
|
||||||
|
values.put(Cols.PHONE_SCREENSHOTS, Utils.serializeCommaSeparatedString(phoneScreenshots));
|
||||||
|
values.put(Cols.SEVEN_INCH_SCREENSHOTS, Utils.serializeCommaSeparatedString(sevenInchScreenshots));
|
||||||
|
values.put(Cols.TEN_INCH_SCREENSHOTS, Utils.serializeCommaSeparatedString(tenInchScreenshots));
|
||||||
|
values.put(Cols.TV_SCREENSHOTS, Utils.serializeCommaSeparatedString(tvScreenshots));
|
||||||
|
values.put(Cols.WEAR_SCREENSHOTS, Utils.serializeCommaSeparatedString(wearScreenshots));
|
||||||
values.put(Cols.IS_COMPATIBLE, compatible ? 1 : 0);
|
values.put(Cols.IS_COMPATIBLE, compatible ? 1 : 0);
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
@ -674,6 +895,14 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
dest.writeStringArray(this.requirements);
|
dest.writeStringArray(this.requirements);
|
||||||
dest.writeString(this.iconUrl);
|
dest.writeString(this.iconUrl);
|
||||||
dest.writeString(this.iconUrlLarge);
|
dest.writeString(this.iconUrlLarge);
|
||||||
|
dest.writeString(this.featureGraphic);
|
||||||
|
dest.writeString(this.promoGraphic);
|
||||||
|
dest.writeString(this.tvBanner);
|
||||||
|
dest.writeStringArray(this.phoneScreenshots);
|
||||||
|
dest.writeStringArray(this.sevenInchScreenshots);
|
||||||
|
dest.writeStringArray(this.tenInchScreenshots);
|
||||||
|
dest.writeStringArray(this.tvScreenshots);
|
||||||
|
dest.writeStringArray(this.wearScreenshots);
|
||||||
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);
|
||||||
@ -713,6 +942,14 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
this.requirements = in.createStringArray();
|
this.requirements = in.createStringArray();
|
||||||
this.iconUrl = in.readString();
|
this.iconUrl = in.readString();
|
||||||
this.iconUrlLarge = in.readString();
|
this.iconUrlLarge = in.readString();
|
||||||
|
this.featureGraphic = in.readString();
|
||||||
|
this.promoGraphic = in.readString();
|
||||||
|
this.tvBanner = in.readString();
|
||||||
|
this.phoneScreenshots = in.createStringArray();
|
||||||
|
this.sevenInchScreenshots = in.createStringArray();
|
||||||
|
this.tenInchScreenshots = in.createStringArray();
|
||||||
|
this.tvScreenshots = in.createStringArray();
|
||||||
|
this.wearScreenshots = in.createStringArray();
|
||||||
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());
|
||||||
|
@ -140,6 +140,14 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
+ AppMetadataTable.Cols.IS_COMPATIBLE + " int not null,"
|
+ AppMetadataTable.Cols.IS_COMPATIBLE + " int not null,"
|
||||||
+ AppMetadataTable.Cols.ICON_URL + " text, "
|
+ AppMetadataTable.Cols.ICON_URL + " text, "
|
||||||
+ AppMetadataTable.Cols.ICON_URL_LARGE + " text, "
|
+ AppMetadataTable.Cols.ICON_URL_LARGE + " text, "
|
||||||
|
+ AppMetadataTable.Cols.FEATURE_GRAPHIC + " string,"
|
||||||
|
+ AppMetadataTable.Cols.PROMO_GRAPHIC + " string,"
|
||||||
|
+ AppMetadataTable.Cols.TV_BANNER + " string,"
|
||||||
|
+ AppMetadataTable.Cols.PHONE_SCREENSHOTS + " string,"
|
||||||
|
+ AppMetadataTable.Cols.SEVEN_INCH_SCREENSHOTS + " string,"
|
||||||
|
+ AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS + " string,"
|
||||||
|
+ AppMetadataTable.Cols.TV_SCREENSHOTS + " string,"
|
||||||
|
+ AppMetadataTable.Cols.WEAR_SCREENSHOTS + " string,"
|
||||||
+ "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
|
||||||
@ -182,7 +190,7 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
+ InstalledAppTable.Cols.HASH + " TEXT NOT NULL"
|
+ InstalledAppTable.Cols.HASH + " TEXT NOT NULL"
|
||||||
+ " );";
|
+ " );";
|
||||||
|
|
||||||
protected static final int DB_VERSION = 66;
|
protected static final int DB_VERSION = 67;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
@ -263,6 +271,47 @@ class DBHelper extends SQLiteOpenHelper {
|
|||||||
addObbFiles(db, oldVersion);
|
addObbFiles(db, oldVersion);
|
||||||
addCategoryTables(db, oldVersion);
|
addCategoryTables(db, oldVersion);
|
||||||
addIndexV1Fields(db, oldVersion);
|
addIndexV1Fields(db, oldVersion);
|
||||||
|
addIndexV1AppFields(db, oldVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addIndexV1AppFields(SQLiteDatabase db, int oldVersion) {
|
||||||
|
if (oldVersion >= 67) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Strings
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.FEATURE_GRAPHIC)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.FEATURE_GRAPHIC + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.FEATURE_GRAPHIC + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.PROMO_GRAPHIC)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.PROMO_GRAPHIC + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.PROMO_GRAPHIC + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.TV_BANNER)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.TV_BANNER + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.TV_BANNER + " string;");
|
||||||
|
}
|
||||||
|
// String Arrays
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.PHONE_SCREENSHOTS)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.PHONE_SCREENSHOTS + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.PHONE_SCREENSHOTS + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.SEVEN_INCH_SCREENSHOTS)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.SEVEN_INCH_SCREENSHOTS + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.SEVEN_INCH_SCREENSHOTS + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.TEN_INCH_SCREENSHOTS + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.TV_SCREENSHOTS)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.TV_SCREENSHOTS + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.TV_SCREENSHOTS + " string;");
|
||||||
|
}
|
||||||
|
if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.WEAR_SCREENSHOTS)) {
|
||||||
|
Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.WEAR_SCREENSHOTS + " field to " + AppMetadataTable.NAME + " table in db.");
|
||||||
|
db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.WEAR_SCREENSHOTS + " string;");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIndexV1Fields(SQLiteDatabase db, int oldVersion) {
|
private void addIndexV1Fields(SQLiteDatabase db, int oldVersion) {
|
||||||
|
@ -143,6 +143,14 @@ public interface Schema {
|
|||||||
String REQUIREMENTS = "requirements";
|
String REQUIREMENTS = "requirements";
|
||||||
String ICON_URL = "iconUrl";
|
String ICON_URL = "iconUrl";
|
||||||
String ICON_URL_LARGE = "iconUrlLarge";
|
String ICON_URL_LARGE = "iconUrlLarge";
|
||||||
|
String FEATURE_GRAPHIC = "featureGraphic";
|
||||||
|
String PROMO_GRAPHIC = "promoGraphic";
|
||||||
|
String TV_BANNER = "tvBanner";
|
||||||
|
String PHONE_SCREENSHOTS = "phoneScreenshots";
|
||||||
|
String SEVEN_INCH_SCREENSHOTS = "sevenInchScreenshots";
|
||||||
|
String TEN_INCH_SCREENSHOTS = "tenInchScreenshots";
|
||||||
|
String TV_SCREENSHOTS = "tvScreenshots";
|
||||||
|
String WEAR_SCREENSHOTS = "wearScreenshots";
|
||||||
|
|
||||||
interface SuggestedApk {
|
interface SuggestedApk {
|
||||||
String VERSION_NAME = "suggestedApkVersion";
|
String VERSION_NAME = "suggestedApkVersion";
|
||||||
@ -180,6 +188,8 @@ public interface Schema {
|
|||||||
CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID,
|
CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID,
|
||||||
UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED,
|
UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED,
|
||||||
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
||||||
|
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
||||||
|
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
||||||
SUGGESTED_VERSION_CODE,
|
SUGGESTED_VERSION_CODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,6 +204,8 @@ public interface Schema {
|
|||||||
CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID,
|
CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID,
|
||||||
UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED,
|
UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED,
|
||||||
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE,
|
||||||
|
FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS,
|
||||||
|
SEVEN_INCH_SCREENSHOTS, TEN_INCH_SCREENSHOTS, TV_SCREENSHOTS, WEAR_SCREENSHOTS,
|
||||||
SUGGESTED_VERSION_CODE, SuggestedApk.VERSION_NAME,
|
SUGGESTED_VERSION_CODE, 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,
|
||||||
|
@ -12,20 +12,21 @@ import android.widget.ImageView;
|
|||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||||
import com.nostra13.universalimageloader.core.download.ImageDownloader;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
|
|
||||||
public class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements LinearLayoutManagerSnapHelper.LinearSnapHelperListener {
|
public class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements LinearLayoutManagerSnapHelper.LinearSnapHelperListener {
|
||||||
|
private final String[] screenshots;
|
||||||
private final DisplayImageOptions displayImageOptions;
|
private final DisplayImageOptions displayImageOptions;
|
||||||
private View selectedView;
|
private View selectedView;
|
||||||
private int selectedPosition;
|
private int selectedPosition;
|
||||||
private final int selectedItemElevation;
|
private final int selectedItemElevation;
|
||||||
private final int unselectedItemMargin;
|
private final int unselectedItemMargin;
|
||||||
|
|
||||||
public ScreenShotsRecyclerViewAdapter(Context context, @SuppressWarnings("unused") App app) {
|
public ScreenShotsRecyclerViewAdapter(Context context, App app) {
|
||||||
super();
|
super();
|
||||||
|
screenshots = app.getAllScreenshots(context);
|
||||||
selectedPosition = 0;
|
selectedPosition = 0;
|
||||||
selectedItemElevation = context.getResources().getDimensionPixelSize(R.dimen.details_screenshot_selected_elevation);
|
selectedItemElevation = context.getResources().getDimensionPixelSize(R.dimen.details_screenshot_selected_elevation);
|
||||||
unselectedItemMargin = context.getResources().getDimensionPixelSize(R.dimen.details_screenshot_margin);
|
unselectedItemMargin = context.getResources().getDimensionPixelSize(R.dimen.details_screenshot_margin);
|
||||||
@ -46,8 +47,8 @@ public class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter<Recycle
|
|||||||
if (position == selectedPosition) {
|
if (position == selectedPosition) {
|
||||||
this.selectedView = vh.itemView;
|
this.selectedView = vh.itemView;
|
||||||
}
|
}
|
||||||
// For now, use the screenshot placeholder
|
ImageLoader.getInstance().displayImage(screenshots[position],
|
||||||
ImageLoader.getInstance().displayImage(ImageDownloader.Scheme.ASSETS.wrap("screenshot_placeholder.png"), vh.image, displayImageOptions);
|
vh.image, displayImageOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -59,7 +60,7 @@ public class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter<Recycle
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return 7;
|
return screenshots.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user