diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/SwapService.java b/app/src/full/java/org/fdroid/fdroid/nearby/SwapService.java
index 358cde6f0..2549d41fc 100644
--- a/app/src/full/java/org/fdroid/fdroid/nearby/SwapService.java
+++ b/app/src/full/java/org/fdroid/fdroid/nearby/SwapService.java
@@ -33,6 +33,7 @@ import org.fdroid.index.IndexParserKt;
import org.fdroid.index.SigningException;
import org.fdroid.index.v1.IndexV1;
import org.fdroid.index.v1.IndexV1Verifier;
+import org.fdroid.index.v2.FileV2;
import java.io.File;
import java.io.IOException;
@@ -130,11 +131,12 @@ public class SwapService extends Service {
private void updateRepo(@NonNull Peer peer, Repository repo)
throws IOException, InterruptedException, SigningException {
Uri uri = Uri.parse(repo.getAddress()).buildUpon().appendPath("index-v1.jar").build();
+ FileV2 indexFile = FileV2.fromPath("/index-v1.jar");
File swapJarFile =
File.createTempFile("swap", "", getApplicationContext().getCacheDir());
try {
Downloader downloader =
- DownloaderFactory.INSTANCE.createWithTryFirstMirror(repo, uri, swapJarFile);
+ DownloaderFactory.INSTANCE.createWithTryFirstMirror(repo, uri, indexFile, swapJarFile);
downloader.download();
IndexV1Verifier verifier = new IndexV1Verifier(swapJarFile, null, peer.getFingerprint());
Pair pair = verifier.getStreamAndVerify(inputStream ->
diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/SwapSuccessView.java b/app/src/full/java/org/fdroid/fdroid/nearby/SwapSuccessView.java
index 8dac0a7d8..b20a5ca18 100644
--- a/app/src/full/java/org/fdroid/fdroid/nearby/SwapSuccessView.java
+++ b/app/src/full/java/org/fdroid/fdroid/nearby/SwapSuccessView.java
@@ -40,6 +40,8 @@ import org.fdroid.index.v1.AppV1;
import org.fdroid.index.v1.IndexV1;
import org.fdroid.index.v1.PackageV1;
import org.fdroid.index.v1.PermissionV1;
+import org.fdroid.index.v2.FileV1;
+import org.fdroid.index.v2.FileV2;
import java.util.ArrayList;
import java.util.HashMap;
@@ -98,7 +100,7 @@ public class SwapSuccessView extends SwapView {
App app = new App();
app.name = a.getName();
app.packageName = a.getPackageName();
- app.iconUrl = "icons/" + a.getIcon();
+ app.iconFile = FileV2.fromPath("icons/" + a.getIcon());
try {
PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(app.packageName, 0);
app.installedVersionCode = packageInfo.versionCode;
@@ -115,9 +117,7 @@ public class SwapSuccessView extends SwapView {
apk.versionCode = packageV1.getVersionCode();
}
apk.versionName = packageV1.getVersionName();
- apk.apkName = packageV1.getApkName();
- apk.hashType = packageV1.getHashType();
- apk.hash = packageV1.getHash();
+ apk.apkFile = new FileV1("/" + packageV1.getApkName(), packageV1.getHash(), packageV1.getSize(), null);
ArrayList permissions =
new ArrayList<>(packageV1.getUsesPermission().size());
for (PermissionV1 perm : packageV1.getUsesPermission()) {
@@ -313,9 +313,8 @@ public class SwapSuccessView extends SwapView {
nameView.setText(app.name);
}
- String path = app.getIconPath(getContext());
Glide.with(iconView.getContext())
- .load(Utils.getDownloadRequest(repo, path))
+ .load(Utils.getDownloadRequest(repo, app.iconFile))
.apply(Utils.getAlwaysShowIconRequestOptions())
.into(iconView);
diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java
index 670478b72..ccc89d7c5 100644
--- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java
+++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java
@@ -294,12 +294,13 @@ public final class AppUpdateStatusManager {
}
private void updateApkInternal(@NonNull AppUpdateStatus entry, @NonNull Status status, PendingIntent intent) {
+ String apkName = entry.apk.getApkPath();
if (status == Status.UpdateAvailable && entry.status.ordinal() > status.ordinal()) {
- Utils.debugLog(LOGTAG, "Not updating APK " + entry.apk.apkName + " state to " + status.name());
+ Utils.debugLog(LOGTAG, "Not updating APK " + apkName + " state to " + status.name());
// If we have this entry in a more advanced state already, don't downgrade it
return;
} else {
- Utils.debugLog(LOGTAG, "Update APK " + entry.apk.apkName + " state to " + status.name());
+ Utils.debugLog(LOGTAG, "Update APK " + apkName + " state to " + status.name());
}
boolean isStatusUpdate = entry.status != status;
entry.status = status;
@@ -315,7 +316,8 @@ public final class AppUpdateStatusManager {
}
private void addApkInternal(@NonNull App app, @NonNull Apk apk, @NonNull Status status, PendingIntent intent) {
- Utils.debugLog(LOGTAG, "Add APK " + apk.apkName + " with state " + status.name());
+ String apkName = apk.getApkPath();
+ Utils.debugLog(LOGTAG, "Add APK " + apkName + " with state " + status.name());
AppUpdateStatus entry = createAppEntry(app, apk, status, intent);
setEntryContentIntentIfEmpty(entry);
appMapping.put(entry.getCanonicalUrl(), entry);
@@ -463,7 +465,7 @@ public final class AppUpdateStatusManager {
InstallManagerService.removePendingInstall(context, canonicalUrl);
AppUpdateStatus entry = appMapping.remove(canonicalUrl);
if (entry != null) {
- Utils.debugLog(LOGTAG, "Remove APK " + entry.apk.apkName);
+ Utils.debugLog(LOGTAG, "Remove APK " + entry.apk.getApkPath());
notifyRemove(entry);
}
}
@@ -473,7 +475,7 @@ public final class AppUpdateStatusManager {
synchronized (appMapping) {
AppUpdateStatus entry = appMapping.get(canonicalUrl);
if (entry != null) {
- Utils.debugLog(LOGTAG, "Refresh APK " + entry.apk.apkName);
+ Utils.debugLog(LOGTAG, "Refresh APK " + entry.apk.getApkPath());
notifyChange(entry, true);
}
}
diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java
index 091d61687..d8b1203f4 100644
--- a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java
+++ b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java
@@ -548,7 +548,7 @@ public class NotificationHelper {
}
});
} else {
- App.loadBitmapWithGlide(context, entry.app.repoId, entry.app.getIconPath(context))
+ App.loadBitmapWithGlide(context, entry.app.repoId, entry.app.getIconPath())
.into(new CustomTarget() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition super Bitmap> transition) {
diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java
index 76f17edc5..1567e20af 100644
--- a/app/src/main/java/org/fdroid/fdroid/Utils.java
+++ b/app/src/main/java/org/fdroid/fdroid/Utils.java
@@ -52,6 +52,7 @@ import com.google.zxing.BarcodeFormat;
import com.google.zxing.encode.Contents;
import com.google.zxing.encode.QRCodeEncoder;
+import org.fdroid.IndexFile;
import org.fdroid.database.AppOverviewItem;
import org.fdroid.database.Repository;
import org.fdroid.download.DownloadRequest;
@@ -77,6 +78,7 @@ import java.net.Socket;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
@@ -475,27 +477,20 @@ public final class Utils {
* @see Preferences#isBackgroundDownloadAllowed()
*/
public static void setIconFromRepoOrPM(@NonNull App app, ImageView iv, Context context) {
- long repoId = app.repoId;
- String iconPath = app.iconFromApk;
- if (iconPath == null) {
- Glide.with(context).clear(iv);
- iv.setImageResource(R.drawable.ic_repo_app_default);
- } else {
- loadWithGlide(context, repoId, iconPath, iv);
- }
+ loadWithGlide(context, app.repoId, app.iconFile, iv);
}
@Deprecated
public static void setIconFromRepoOrPM(@NonNull AppOverviewItem app, ImageView iv, Context context) {
long repoId = app.getRepoId();
- FileV2 iconFile = app.getIcon(App.getLocales());
- String iconPath = iconFile == null ? null : iconFile.getName();
- loadWithGlide(context, repoId, iconPath, iv);
+ IndexFile iconFile = app.getIcon(App.getLocales());
+ loadWithGlide(context, repoId, iconFile, iv);
}
- private static void loadWithGlide(Context context, long repoId, String iconPath, ImageView iv) {
- if (iconPath == null) {
+ public static void loadWithGlide(Context context, long repoId, @Nullable IndexFile file, ImageView iv) {
+ if (file == null) {
Glide.with(context).clear(iv);
+ iv.setImageResource(R.drawable.ic_repo_app_default);
return;
}
if (iconRequestOptions == null) {
@@ -513,15 +508,24 @@ public final class Utils {
}
String address = getRepoAddress(repo);
if (address.startsWith("content://")) {
- String uri = getUri(address, iconPath.split("/")).toString();
+ String uri = getUri(address, file.getName().split("/")).toString();
Glide.with(context).load(uri).apply(options).into(iv);
} else {
- DownloadRequest request = getDownloadRequest(repo, iconPath);
+ DownloadRequest request = getDownloadRequest(repo, file);
Glide.with(context).load(request).apply(options).into(iv);
}
}
@Nullable
+ public static DownloadRequest getDownloadRequest(@NonNull Repository repo, @Nullable IndexFile file) {
+ if (file == null) return null;
+ List mirrors = repo.getMirrors();
+ Proxy proxy = NetCipher.getProxy();
+ return new DownloadRequest(file, mirrors, proxy, repo.getUsername(), repo.getPassword());
+ }
+
+ @Nullable
+ @Deprecated
public static DownloadRequest getDownloadRequest(@NonNull Repository repo, @Nullable String path) {
if (path == null) return null;
List mirrors = repo.getMirrors();
@@ -854,6 +858,23 @@ public final class Utils {
});
}
+ public static ArrayList toString(@Nullable List files) {
+ if (files == null) return new ArrayList<>(0);
+ ArrayList list = new ArrayList<>(files.size());
+ for (FileV2 file : files) {
+ list.add(file.serialize());
+ }
+ return list;
+ }
+
+ public static List fileV2FromStrings(List list) {
+ ArrayList files = new ArrayList<>(list.size());
+ for (String s : list) {
+ files.add(FileV2.deserialize(s));
+ }
+ return files;
+ }
+
/**
* Keep an instance of this class as an field in an AppCompatActivity for figuring out whether the on
* screen keyboard is currently visible or not.
diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java
index 653627ca9..741c7a4f3 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java
@@ -19,6 +19,7 @@ import org.fdroid.fdroid.CompatibilityChecker;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.installer.ApkCache;
+import org.fdroid.index.v2.FileV1;
import org.fdroid.index.v2.PermissionV2;
import org.fdroid.index.v2.SignerV2;
@@ -60,7 +61,6 @@ public class Apk implements Comparable, Parcelable {
// these are never set by the Apk/package index metadata
public String repoAddress;
public String canonicalRepoAddress;
- long repoVersion;
public SanitizedFile installedFile; // the .apk file on this device's filesystem
public boolean compatible; // True if compatible with the device.
public long repoId; // the database ID of the repo it comes from
@@ -107,13 +107,20 @@ public class Apk implements Comparable, Parcelable {
*/
public String sig;
- public String apkName; // F-Droid style APK name
+ /**
+ * Can be null when created with {@link #Apk(PackageInfo)}
+ * which happens only for showing an installed version
+ * in {@link org.fdroid.fdroid.views.AppDetailsActivity}.
+ */
+ @Nullable
+ public FileV1 apkFile;
/**
* If not null, this is the name of the source tarball for the
* application. Null indicates that it's a developer's binary
* build - otherwise it's built from source.
*/
+ @Nullable
public String srcname;
public String[] incompatibleReasons;
@@ -122,11 +129,6 @@ public class Apk implements Comparable, Parcelable {
public String whatsNew;
- /**
- * The numeric primary key of the Metadata table, which is used to join apks.
- */
- public long appId;
-
public Apk() {
}
@@ -154,9 +156,6 @@ public class Apk implements Comparable, Parcelable {
Repository repo = Objects.requireNonNull(FDroidApp.getRepo(v.getRepoId()));
repoAddress = Utils.getRepoAddress(repo);
canonicalRepoAddress = repo.getAddress();
- repoVersion = repo.getVersion();
- hash = v.getFile().getSha256();
- hashType = "sha256";
added = new Date(v.getAdded());
features = v.getFeatureNames().toArray(new String[0]);
setPackageName(v.getPackageName());
@@ -174,11 +173,7 @@ public class Apk implements Comparable, Parcelable {
} else {
releaseChannels = channels;
}
- // obbMainFile = cursor.getString(i);
- // obbMainFileSha256 = cursor.getString(i);
- // obbPatchFile = cursor.getString(i);
- // obbPatchFileSha256 = cursor.getString(i);
- apkName = v.getFile().getName();
+ apkFile = v.getFile();
setRequestedPermissions(v.getUsesPermission(), 0);
setRequestedPermissions(v.getUsesPermissionSdk23(), 23);
nativecode = v.getNativeCode().toArray(new String[0]);
@@ -205,18 +200,23 @@ public class Apk implements Comparable, Parcelable {
}
private void checkRepoAddress() {
- if (repoAddress == null || apkName == null) {
+ if (repoAddress == null || apkFile == null) {
throw new IllegalStateException(
"Apk needs to have both Schema.ApkTable.Cols.REPO_ADDRESS and "
+ "Schema.ApkTable.Cols.NAME set in order to calculate URL "
+ "[package: " + packageName
+ ", versionCode: " + versionCode
- + ", apkName: " + apkName
+ + ", apkName: " + getApkPath()
+ ", repoAddress: " + repoAddress
+ ", repoId: " + repoId + "]");
}
}
+ @Nullable
+ public String getApkPath() {
+ return apkFile == null ? "" : apkFile.getName();
+ }
+
/**
* Get the URL that points to the canonical download source for this
* package. This is also used as the unique ID for tracking downloading,
@@ -229,12 +229,12 @@ public class Apk implements Comparable, Parcelable {
public String getCanonicalUrl() {
checkRepoAddress();
/* Each String in pathElements might contain a /, should keep these as path elements */
- return Utils.getUri(canonicalRepoAddress, apkName.split("/")).toString();
+ return Utils.getUri(canonicalRepoAddress, getApkPath().split("/")).toString();
}
public String getDownloadUrl() {
checkRepoAddress();
- return Utils.getUri(repoAddress, apkName.split("/")).toString();
+ return Utils.getUri(repoAddress, getApkPath().split("/")).toString();
}
/**
@@ -311,8 +311,6 @@ public class Apk implements Comparable, Parcelable {
dest.writeLong(this.versionCode);
dest.writeLong(this.size);
dest.writeLong(this.repoId);
- dest.writeString(this.hash);
- dest.writeString(this.hashType);
dest.writeInt(this.minSdkVersion);
dest.writeInt(this.targetSdkVersion);
dest.writeInt(this.maxSdkVersion);
@@ -326,15 +324,13 @@ public class Apk implements Comparable, Parcelable {
dest.writeStringArray(this.nativecode);
dest.writeString(this.sig);
dest.writeByte(this.compatible ? (byte) 1 : (byte) 0);
- dest.writeString(this.apkName);
+ dest.writeString(this.apkFile.serialize());
dest.writeSerializable(this.installedFile);
dest.writeString(this.srcname);
- dest.writeLong(this.repoVersion);
dest.writeString(this.repoAddress);
dest.writeString(this.canonicalRepoAddress);
dest.writeStringArray(this.incompatibleReasons);
dest.writeStringArray(this.antiFeatures);
- dest.writeLong(this.appId);
}
protected Apk(Parcel in) {
@@ -343,8 +339,6 @@ public class Apk implements Comparable, Parcelable {
this.versionCode = in.readLong();
this.size = in.readLong();
this.repoId = in.readLong();
- this.hash = in.readString();
- this.hashType = in.readString();
this.minSdkVersion = in.readInt();
this.targetSdkVersion = in.readInt();
this.maxSdkVersion = in.readInt();
@@ -359,15 +353,13 @@ public class Apk implements Comparable, Parcelable {
this.nativecode = in.createStringArray();
this.sig = in.readString();
this.compatible = in.readByte() != 0;
- this.apkName = in.readString();
+ this.apkFile = FileV1.deserialize(in.readString());
this.installedFile = (SanitizedFile) in.readSerializable();
this.srcname = in.readString();
- this.repoVersion = in.readLong();
this.repoAddress = in.readString();
this.canonicalRepoAddress = in.readString();
this.incompatibleReasons = in.createStringArray();
this.antiFeatures = in.createStringArray();
- this.appId = in.readLong();
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@@ -536,7 +528,7 @@ public class Apk implements Comparable, Parcelable {
}
public File getInstalledMediaFile(Context context) {
- return new File(this.getMediaInstallPath(context), SanitizedFile.sanitizeFileName(this.apkName));
+ return new File(this.getMediaInstallPath(context), SanitizedFile.sanitizeFileName(getApkPath()));
}
/**
@@ -554,7 +546,8 @@ public class Apk implements Comparable, Parcelable {
* @return true if this is an apk instead of a non-apk/media file
*/
public boolean isApk() {
- return apkName == null
- || apkName.substring(apkName.length() - 4).toLowerCase(Locale.ENGLISH).endsWith(".apk");
+ return apkFile == null
+ || apkFile.getName().substring(apkFile.getName().length() - 4)
+ .toLowerCase(Locale.ENGLISH).endsWith(".apk");
}
}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java
index 35e3d1de8..4d1bf39eb 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/App.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/App.java
@@ -19,6 +19,7 @@ import android.util.Log;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
+import org.fdroid.IndexFile;
import org.fdroid.database.AppListItem;
import org.fdroid.database.Repository;
import org.fdroid.database.UpdatableApp;
@@ -86,16 +87,10 @@ public class App implements Comparable, Parcelable {
public String installedSig;
public int installedVersionCode;
public String installedVersionName;
- private long id;
public org.fdroid.database.AppPrefs prefs;
public String preferredSigner;
public boolean isApk;
- /**
- * Has this {@code App} been localized into one of the user's current locales.
- */
- boolean isLocalized;
-
/**
* This is primarily for the purpose of saving app metadata when parsing an index.xml file.
* At most other times, we don't particularly care which repo an {@link App} object came from.
@@ -110,7 +105,6 @@ public class App implements Comparable, Parcelable {
public String name = "Unknown";
public String summary = "Unknown application";
- public String iconFromApk;
public String description;
@@ -119,15 +113,15 @@ public class App implements Comparable, Parcelable {
*/
public String whatsNew;
- public String featureGraphic;
- public String promoGraphic;
- public String tvBanner;
+ public FileV2 featureGraphic;
+ private FileV2 promoGraphic;
+ private FileV2 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 List phoneScreenshots = Collections.emptyList();
+ private List sevenInchScreenshots = Collections.emptyList();
+ private List tenInchScreenshots = Collections.emptyList();
+ private List tvScreenshots = Collections.emptyList();
+ private List wearScreenshots = Collections.emptyList();
public String license;
@@ -205,18 +199,7 @@ public class App implements Comparable, Parcelable {
@Nullable
public String[] antiFeatures;
- /**
- * Requires root access (only ever used for root)
- */
- @Nullable
- @Deprecated
- public String[] requirements;
-
- /**
- * URL to download the app's icon. (Set only from localized block, see also
- * {@link #iconFromApk} and {@link #getIconPath(Context)} (Context)}
- */
- public String iconUrl;
+ public FileV2 iconFile;
@Override
public int compareTo(@NonNull App app) {
@@ -227,20 +210,16 @@ public class App implements Comparable, Parcelable {
}
public App(final UpdatableApp app) {
- id = 0;
repoId = app.getUpdate().getRepoId();
setPackageName(app.getPackageName());
name = app.getName() == null ? "" : app.getName();
summary = app.getSummary() == null ? "" : app.getSummary();
installedVersionCode = (int) app.getInstalledVersionCode();
autoInstallVersionCode = (int) app.getUpdate().getManifest().getVersionCode();
- FileV2 icon = app.getIcon(getLocales());
- iconUrl = icon == null ? null : icon.getName();
- iconFromApk = icon == null ? null : icon.getName();
+ iconFile = app.getIcon(getLocales());
}
public App(final org.fdroid.database.App app, @Nullable PackageInfo packageInfo) {
- id = 0;
repoId = app.getRepoId();
compatible = app.getMetadata().isCompatible();
setPackageName(app.getPackageName());
@@ -269,40 +248,15 @@ public class App implements Comparable, Parcelable {
preferredSigner = app.getMetadata().getPreferredSigner();
added = new Date(app.getMetadata().getAdded());
lastUpdated = new Date(app.getMetadata().getLastUpdated());
- FileV2 icon = app.getIcon(getLocales());
- iconUrl = icon == null ? null : icon.getName();
- iconFromApk = icon == null ? null : icon.getName();
- FileV2 featureGraphic = app.getFeatureGraphic(getLocales());
- this.featureGraphic = featureGraphic == null ? null : featureGraphic.getName();
- FileV2 promoGraphic = app.getPromoGraphic(getLocales());
- this.promoGraphic = promoGraphic == null ? null : promoGraphic.getName();
- FileV2 tvBanner = app.getPromoGraphic(getLocales());
- this.tvBanner = tvBanner == null ? null : tvBanner.getName();
- List phoneFiles = app.getPhoneScreenshots(getLocales());
- phoneScreenshots = new String[phoneFiles.size()];
- for (int i = 0; i < phoneFiles.size(); i++) {
- phoneScreenshots[i] = phoneFiles.get(i).getName();
- }
- List sevenInchFiles = app.getSevenInchScreenshots(getLocales());
- sevenInchScreenshots = new String[sevenInchFiles.size()];
- for (int i = 0; i < sevenInchFiles.size(); i++) {
- phoneScreenshots[i] = sevenInchFiles.get(i).getName();
- }
- List tenInchFiles = app.getTenInchScreenshots(getLocales());
- tenInchScreenshots = new String[tenInchFiles.size()];
- for (int i = 0; i < tenInchFiles.size(); i++) {
- phoneScreenshots[i] = tenInchFiles.get(i).getName();
- }
- List tvFiles = app.getTvScreenshots(getLocales());
- tvScreenshots = new String[tvFiles.size()];
- for (int i = 0; i < tvFiles.size(); i++) {
- phoneScreenshots[i] = tvFiles.get(i).getName();
- }
- List wearFiles = app.getWearScreenshots(getLocales());
- wearScreenshots = new String[wearFiles.size()];
- for (int i = 0; i < wearFiles.size(); i++) {
- phoneScreenshots[i] = wearFiles.get(i).getName();
- }
+ iconFile = app.getIcon(getLocales());
+ featureGraphic = app.getFeatureGraphic(getLocales());
+ promoGraphic = app.getPromoGraphic(getLocales());
+ tvBanner = app.getPromoGraphic(getLocales());
+ phoneScreenshots = app.getPhoneScreenshots(getLocales());
+ sevenInchScreenshots = app.getSevenInchScreenshots(getLocales());
+ tenInchScreenshots = app.getTenInchScreenshots(getLocales());
+ tvScreenshots = app.getTvScreenshots(getLocales());
+ wearScreenshots = app.getWearScreenshots(getLocales());
setInstalled(packageInfo);
}
@@ -311,8 +265,7 @@ public class App implements Comparable, Parcelable {
setPackageName(item.getPackageName());
name = item.getName() == null ? "" : item.getName();
summary = item.getSummary() == null ? "" : item.getSummary();
- FileV2 iconFile = item.getIcon(getLocales());
- iconFromApk = iconFile == null ? null : iconFile.getName();
+ iconFile = item.getIcon(getLocales());
installedVersionCode = item.getInstalledVersionCode() == null ? 0 : item.getInstalledVersionCode().intValue();
installedVersionName = item.getInstalledVersionName();
antiFeatures = item.getAntiFeatureKeys().toArray(new String[0]);
@@ -367,7 +320,7 @@ public class App implements Comparable, Parcelable {
/**
* Set the Package Name property while ensuring it is sanitized.
*/
- void setPackageName(String packageName) {
+ private void setPackageName(String packageName) {
if (Utils.isSafePackageName(packageName)) {
this.packageName = packageName;
} else {
@@ -379,7 +332,7 @@ public class App implements Comparable, Parcelable {
/**
* Returns the app description text with all newlines replaced by {@code
}
*/
- public static String formatDescription(String description) {
+ private static String formatDescription(String description) {
return description.replace("\n", "
");
}
@@ -395,11 +348,11 @@ public class App implements Comparable, Parcelable {
.build();
}
- public RequestBuilder loadWithGlide(Context context, String path) {
- return loadWithGlide(context, repoId, path);
+ public RequestBuilder loadWithGlide(Context context, IndexFile file) {
+ return loadWithGlide(context, repoId, file);
}
- public static RequestBuilder loadWithGlide(Context context, long repoId, String path) {
+ public static RequestBuilder loadWithGlide(Context context, long repoId, IndexFile file) {
Repository repo = FDroidApp.getRepo(repoId);
if (repo == null) { // This is also used for apps that do not have a repo
return Glide.with(context).load((Drawable) null);
@@ -410,12 +363,12 @@ public class App implements Comparable, Parcelable {
}
String address = Utils.getRepoAddress(repo);
if (address.startsWith("content://")) {
- String sb = Utils.getUri(address, path.split("/")).toString();
+ String sb = Utils.getUri(address, file.getName().split("/")).toString();
return Glide.with(context).load(sb);
} else if (address.startsWith("file://")) {
- return Glide.with(context).load(path);
+ return Glide.with(context).load(file);
} else {
- return Glide.with(context).load(Utils.getDownloadRequest(repo, path));
+ return Glide.with(context).load(Utils.getDownloadRequest(repo, file));
}
}
@@ -438,23 +391,18 @@ public class App implements Comparable, Parcelable {
}
}
- public String getIconPath(Context context) {
- String path;
- if (TextUtils.isEmpty(iconUrl)) {
- if (TextUtils.isEmpty(iconFromApk)) {
- return null;
- }
- if (iconFromApk.endsWith(".xml")) {
- // We cannot use xml resources as icons. F-Droid server should not include them
- // https://gitlab.com/fdroid/fdroidserver/issues/344
- return null;
- }
- String iconsDir = Utils.getIconsDir(context, 1.0);
- path = getPath(iconsDir, iconFromApk);
+ public String getIconPath() {
+ if (iconFile == null) {
+ return null;
+ } else if (TextUtils.isEmpty(iconFile.getName())) {
+ return null;
+ } else if (iconFile.getName().endsWith(".xml")) {
+ // We cannot use xml resources as icons. F-Droid server should not include them
+ // https://gitlab.com/fdroid/fdroidserver/issues/344
+ return null;
} else {
- path = iconUrl;
+ return iconFile.getName();
}
- return path;
}
/**
@@ -477,23 +425,12 @@ public class App implements Comparable, Parcelable {
return sb.toString();
}
- public ArrayList getAllScreenshots() {
- ArrayList 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);
- }
+ public List getAllScreenshots() {
+ ArrayList list = new ArrayList<>(phoneScreenshots);
+ list.addAll(sevenInchScreenshots);
+ list.addAll(tenInchScreenshots);
+ list.addAll(tvScreenshots);
+ list.addAll(wearScreenshots);
return list;
}
@@ -737,10 +674,6 @@ public class App implements Comparable, Parcelable {
return new int[]{minSdkVersion, targetSdkVersion, maxSdkVersion};
}
- public long getId() {
- return id;
- }
-
@Override
public int describeContents() {
return 0;
@@ -774,7 +707,7 @@ public class App implements Comparable, Parcelable {
dest.writeString(this.name);
dest.writeLong(this.repoId);
dest.writeString(this.summary);
- dest.writeString(this.iconFromApk);
+ dest.writeString(this.iconFile == null ? null : this.iconFile.serialize());
dest.writeString(this.description);
dest.writeString(this.whatsNew);
dest.writeString(this.license);
@@ -801,23 +734,19 @@ public class App implements Comparable, Parcelable {
dest.writeLong(this.lastUpdated != null ? this.lastUpdated.getTime() : -1);
dest.writeStringArray(this.categories);
dest.writeStringArray(this.antiFeatures);
- dest.writeStringArray(this.requirements);
- dest.writeString(this.iconUrl);
- 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.featureGraphic == null ? null : this.featureGraphic.serialize());
+ dest.writeString(this.promoGraphic == null ? null : this.promoGraphic.serialize());
+ dest.writeString(this.tvBanner == null ? null : this.tvBanner.serialize());
+ dest.writeStringList(Utils.toString(this.phoneScreenshots));
+ dest.writeStringList(Utils.toString(this.sevenInchScreenshots));
+ dest.writeStringList(Utils.toString(this.tenInchScreenshots));
+ dest.writeStringList(Utils.toString(this.tvScreenshots));
+ dest.writeStringList(Utils.toString(this.wearScreenshots));
dest.writeByte(this.isApk ? (byte) 1 : (byte) 0);
- dest.writeByte(this.isLocalized ? (byte) 1 : (byte) 0);
dest.writeString(this.installedVersionName);
dest.writeInt(this.installedVersionCode);
dest.writeParcelable(this.installedApk, flags);
dest.writeString(this.installedSig);
- dest.writeLong(this.id);
}
protected App(Parcel in) {
@@ -826,7 +755,7 @@ public class App implements Comparable, Parcelable {
this.name = in.readString();
this.repoId = in.readLong();
this.summary = in.readString();
- this.iconFromApk = in.readString();
+ this.iconFile = FileV2.deserialize(in.readString());
this.description = in.readString();
this.whatsNew = in.readString();
this.license = in.readString();
@@ -855,23 +784,19 @@ public class App implements Comparable, Parcelable {
this.lastUpdated = tmpLastUpdated == -1 ? null : new Date(tmpLastUpdated);
this.categories = in.createStringArray();
this.antiFeatures = in.createStringArray();
- this.requirements = in.createStringArray();
- this.iconUrl = 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.featureGraphic = FileV2.deserialize(in.readString());
+ this.promoGraphic = FileV2.deserialize(in.readString());
+ this.tvBanner = FileV2.deserialize(in.readString());
+ this.phoneScreenshots = Utils.fileV2FromStrings(in.createStringArrayList());
+ this.sevenInchScreenshots = Utils.fileV2FromStrings(in.createStringArrayList());
+ this.tenInchScreenshots = Utils.fileV2FromStrings(in.createStringArrayList());
+ this.tvScreenshots = Utils.fileV2FromStrings(in.createStringArrayList());
+ this.wearScreenshots = Utils.fileV2FromStrings(in.createStringArrayList());
this.isApk = in.readByte() != 0;
- this.isLocalized = in.readByte() != 0;
this.installedVersionName = in.readString();
this.installedVersionCode = in.readInt();
this.installedApk = in.readParcelable(Apk.class.getClassLoader());
this.installedSig = in.readString();
- this.id = in.readLong();
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
diff --git a/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java b/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java
index ae4218a5f..fd4e0bc78 100644
--- a/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java
+++ b/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java
@@ -59,7 +59,7 @@ public class ApkCache {
throws IOException {
String name = expectedApk.packageName;
String apkFileName = name + "-" + expectedApk.versionName + ".apk";
- return copyApkToFiles(context, apkFile, apkFileName, true, expectedApk.hash, expectedApk.hashType);
+ return copyApkToFiles(context, apkFile, apkFileName, true, expectedApk.apkFile.getSha256(), "sha256");
}
/**
@@ -133,7 +133,7 @@ public class ApkCache {
*/
public static boolean apkIsCached(File apkFile, Apk apkToCheck) {
return apkFile.length() == apkToCheck.size &&
- Utils.isFileMatchingHash(apkFile, apkToCheck.hash, apkToCheck.hashType);
+ Utils.isFileMatchingHash(apkFile, apkToCheck.apkFile.getSha256(), "sha256");
}
/**
diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
index 638dc0f72..36d58c9f9 100644
--- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
+++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java
@@ -15,7 +15,6 @@ import android.util.Log;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
-import org.fdroid.download.Downloader;
import org.fdroid.fdroid.AppUpdateStatusManager;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.compat.PackageManagerCompat;
@@ -69,7 +68,7 @@ import static vendored.org.apache.commons.codec.digest.MessageDigestAlgorithms.S
* for a {@code String} ID, use {@code canonicalUrl}, {@link Uri#toString()}, or
* {@link Intent#getDataString()}
* for an {@code int} ID, use {@link String#hashCode()} or {@link Uri#hashCode()}
- * for an {@link Intent} extra, use {@link Downloader#EXTRA_CANONICAL_URL} and include a
+ * for an {@link Intent} extra, use {@link DownloaderService#EXTRA_CANONICAL_URL} and include a
* {@link String} instance
*
* The implementations of {@link Uri#toString()} and {@link Intent#getDataString()} both
@@ -214,7 +213,7 @@ public class InstallManagerService extends Service {
long apkFileSize = apkFilePath.length();
if (!apkFilePath.exists() || apkFileSize < apk.size) {
Utils.debugLog(TAG, "download " + canonicalUrl + " " + apkFilePath);
- DownloaderService.queue(this, apk.repoId, canonicalUrl, apk.getDownloadUrl());
+ DownloaderService.queue(this, apk.repoId, canonicalUrl, apk.getDownloadUrl(), apk.apkFile);
} else if (ApkCache.apkIsCached(apkFilePath, apk)) {
Utils.debugLog(TAG, "skip download, we have it, straight to install " + canonicalUrl + " " + apkFilePath);
sendBroadcast(intent.getData(), DownloaderService.ACTION_STARTED, apkFilePath);
@@ -222,7 +221,7 @@ public class InstallManagerService extends Service {
} else {
Utils.debugLog(TAG, "delete and download again " + canonicalUrl + " " + apkFilePath);
apkFilePath.delete();
- DownloaderService.queue(this, apk.repoId, canonicalUrl, apk.getDownloadUrl());
+ DownloaderService.queue(this, apk.repoId, canonicalUrl, apk.getDownloadUrl(), apk.apkFile);
}
return START_REDELIVER_INTENT; // if killed before completion, retry Intent
@@ -307,7 +306,7 @@ public class InstallManagerService extends Service {
}
}
};
- DownloaderService.queue(this, repoId, obbUrlString, obbUrlString);
+ DownloaderService.queue(this, repoId, obbUrlString, obbUrlString, null);
localBroadcastManager.registerReceiver(downloadReceiver,
DownloaderService.getIntentFilter(obbUrlString));
}
diff --git a/app/src/main/java/org/fdroid/fdroid/net/BluetoothDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/BluetoothDownloader.java
index 511dadc75..4b4ca5bfc 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/BluetoothDownloader.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/BluetoothDownloader.java
@@ -4,6 +4,7 @@ import android.net.Uri;
import android.util.Log;
import org.apache.commons.io.input.BoundedInputStream;
+import org.fdroid.IndexFile;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.nearby.BluetoothClient;
@@ -39,8 +40,8 @@ public class BluetoothDownloader extends Downloader {
&& Pattern.matches("([0-9A-F]{2}-)+[0-9A-F]{2}", uri.getHost());
}
- public BluetoothDownloader(Uri uri, File destFile) throws IOException {
- super(destFile);
+ BluetoothDownloader(Uri uri, IndexFile indexFile, File destFile) throws IOException {
+ super(indexFile, destFile);
String macAddress = uri.getHost().replace("-", ":");
this.connection = new BluetoothClient(macAddress).openConnection();
this.sourcePath = uri.getPath();
@@ -91,18 +92,11 @@ public class BluetoothDownloader extends Downloader {
@Override
public long totalDownloadSize() {
- if (getFileSize() != null) return getFileSize();
+ if (getIndexFile().getSize() != null) return getIndexFile().getSize();
FileDetails details = getFileDetails();
return details != null ? details.getFileSize() : -1;
}
- @Override
- public void download(long totalSize, @Nullable String sha256) throws IOException, InterruptedException {
- setFileSize(totalSize);
- setSha256(sha256);
- download();
- }
-
@Override
public void download() throws IOException, InterruptedException {
downloadFromStream(false);
diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderFactory.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderFactory.java
index e94b5a8b4..4fdd79307 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderFactory.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderFactory.java
@@ -6,18 +6,23 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import org.fdroid.IndexFile;
import org.fdroid.database.Repository;
import org.fdroid.download.DownloadRequest;
import org.fdroid.download.Downloader;
import org.fdroid.download.HttpDownloader;
+import org.fdroid.download.HttpDownloaderV2;
import org.fdroid.download.HttpManager;
import org.fdroid.download.Mirror;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Utils;
+import org.fdroid.index.IndexFormatVersion;
import java.io.File;
import java.io.IOException;
import java.net.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import info.guardianproject.netcipher.NetCipher;
@@ -32,33 +37,60 @@ public class DownloaderFactory extends org.fdroid.download.DownloaderFactory {
@NonNull
@Override
- public Downloader create(Repository repo, @NonNull Uri uri, @NonNull File destFile) throws IOException {
+ public Downloader create(Repository repo, @NonNull Uri uri, @NonNull IndexFile indexFile,
+ @NonNull File destFile) throws IOException {
List mirrors = repo.getMirrors();
- return create(repo, mirrors, uri, destFile, null);
+ return create(repo, mirrors, uri, indexFile, destFile, null);
}
@NonNull
@Override
protected Downloader create(@NonNull Repository repo, @NonNull List mirrors, @NonNull Uri uri,
- @NonNull File destFile, @Nullable Mirror tryFirst) throws IOException {
+ @NonNull IndexFile indexFile, @NonNull File destFile,
+ @Nullable Mirror tryFirst) throws IOException {
Downloader downloader;
String scheme = uri.getScheme();
if (BluetoothDownloader.SCHEME.equals(scheme)) {
- downloader = new BluetoothDownloader(uri, destFile);
+ downloader = new BluetoothDownloader(uri, indexFile, destFile);
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
- downloader = new TreeUriDownloader(uri, destFile);
+ downloader = new TreeUriDownloader(uri, indexFile, destFile);
} else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
- downloader = new LocalFileDownloader(uri, destFile);
+ downloader = new LocalFileDownloader(uri, indexFile, destFile);
} else {
String repoAddress = Utils.getRepoAddress(repo);
String path = uri.toString().replace(repoAddress, "");
Utils.debugLog(TAG, "Using suffix " + path + " with mirrors " + mirrors);
Proxy proxy = NetCipher.getProxy();
- DownloadRequest request = new DownloadRequest(path, mirrors, proxy, repo.getUsername(),
- repo.getPassword(), tryFirst);
- downloader = new HttpDownloader(HTTP_MANAGER, request, destFile);
+ DownloadRequest request = new DownloadRequest(indexFile, mirrors, proxy,
+ repo.getUsername(), repo.getPassword(), tryFirst);
+ if (repo.getFormatVersion() == null || repo.getFormatVersion() == IndexFormatVersion.ONE) {
+ //noinspection deprecation
+ downloader = new HttpDownloader(HTTP_MANAGER, request, destFile);
+ } else {
+ DownloadRequest r;
+ if (request.getIndexFile().getIpfsCidV1() == null) r = request;
+ else {
+ // add IPFS gateways to mirrors, because have have a CIDv1
+ List m = new ArrayList<>(mirrors);
+ m.addAll(IPFS_MIRRORS);
+ r = new DownloadRequest(request.getIndexFile(), m, proxy, repo.getUsername(),
+ repo.getPassword(), tryFirst);
+ }
+ downloader = new HttpDownloaderV2(HTTP_MANAGER, r, destFile);
+ }
}
return downloader;
}
+
+ private static final List IPFS_MIRRORS = Arrays.asList(
+ new Mirror("https://ipfs.eth.aragon.network/ipfs/", null, true),
+ new Mirror("https://gateway.ipfs.io/ipfs/", null, true),
+ new Mirror("https://ipfs.io/ipfs/", null, true),
+ new Mirror("https://cloudflare-ipfs.com/ipfs/", null, true),
+ new Mirror("https://ipfs.fleek.co/ipfs/", null, true),
+ new Mirror("https://gateway.pinata.cloud/ipfs/", null, true),
+ new Mirror("https://ipfs.filebase.io/ipfs/", null, true)
+ );
+
}
diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java
index 6bc009b86..bef7b389d 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java
@@ -43,6 +43,7 @@ import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.DBHelper;
import org.fdroid.fdroid.data.SanitizedFile;
import org.fdroid.fdroid.installer.ApkCache;
+import org.fdroid.index.v2.FileV1;
import java.io.File;
import java.io.IOException;
@@ -63,11 +64,11 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
/**
* DownloaderService is a service that handles asynchronous download requests
* (expressed as {@link Intent}s) on demand. Clients send download requests
- * through {@link #queue(Context, long, String)} calls. The
+ * through {@link #queue(Context, long, String, String, FileV1)} calls. The
* service is started as needed, it handles each {@code Intent} using a worker
* thread, and stops itself when it runs out of work. Requests can be canceled
* using {@link #cancel(Context, String)}. If this service is killed during
- * operation, it will receive the queued {@link #queue(Context, long, String)}
+ * operation, it will receive the queued {@link #queue(Context, long, String, String, FileV1)}
* and {@link #cancel(Context, String)} requests again due to
* {@link Service#START_REDELIVER_INTENT}. Bad requests will be ignored,
* including on restart after killing via {@link Service#START_NOT_STICKY}.
@@ -123,6 +124,7 @@ public class DownloaderService extends Service {
* @see android.content.Intent#EXTRA_ORIGINATING_URI
*/
public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL";
+ private static final String EXTRA_INDEX_FILE_V1 = "org.fdroid.fdroid.net.Downloader.extra.INDEX_FILE_V1";
private volatile Looper serviceLooper;
private static volatile ServiceHandler serviceHandler;
@@ -246,6 +248,7 @@ public class DownloaderService extends Service {
final Uri canonicalUrl = intent.getData();
final Uri downloadUrl =
Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
+ final FileV1 fileV1 = FileV1.deserialize(intent.getStringExtra(DownloaderService.EXTRA_INDEX_FILE_V1));
final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrl);
sendBroadcast(uri, DownloaderService.ACTION_STARTED, localFile, repoId, canonicalUrl);
@@ -264,7 +267,7 @@ public class DownloaderService extends Service {
} else return; // repo might have been deleted in the meantime
}
}
- downloader = DownloaderFactory.INSTANCE.create(repo, downloadUrl, localFile);
+ downloader = DownloaderFactory.INSTANCE.create(repo, downloadUrl, fileV1, localFile);
downloader.setListener(new ProgressListener() {
@Override
public void onProgress(long bytesRead, long totalBytes) {
@@ -334,7 +337,7 @@ public class DownloaderService extends Service {
* @see #cancel(Context, String)
*/
public static void queue(Context context, long repoId, String canonicalUrl,
- String downloadUrl) {
+ String downloadUrl, FileV1 fileV1) {
if (TextUtils.isEmpty(canonicalUrl)) {
return;
}
@@ -344,6 +347,7 @@ public class DownloaderService extends Service {
intent.setData(Uri.parse(canonicalUrl));
intent.putExtra(DownloaderService.EXTRA_REPO_ID, repoId);
intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, downloadUrl);
+ intent.putExtra(DownloaderService.EXTRA_INDEX_FILE_V1, fileV1.serialize());
context.startService(intent);
}
@@ -354,7 +358,7 @@ public class DownloaderService extends Service {
*
* @param context this app's {@link Context}
* @param canonicalUrl The URL to remove from the download queue
- * @see #queue(Context, long, String)
+ * @see #queue(Context, long, String, String, FileV1
*/
public static void cancel(Context context, String canonicalUrl) {
if (TextUtils.isEmpty(canonicalUrl)) {
diff --git a/app/src/main/java/org/fdroid/fdroid/net/LocalFileDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/LocalFileDownloader.java
index 72cae0aff..3dd522f9c 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/LocalFileDownloader.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/LocalFileDownloader.java
@@ -3,10 +3,10 @@ package org.fdroid.fdroid.net;
import android.net.Uri;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.fdroid.IndexFile;
import org.fdroid.download.Downloader;
import org.fdroid.download.NotFoundException;
@@ -31,8 +31,8 @@ public class LocalFileDownloader extends Downloader {
private InputStream inputStream;
private final File sourceFile;
- LocalFileDownloader(Uri uri, File destFile) {
- super(destFile);
+ LocalFileDownloader(Uri uri, IndexFile indexFile, File destFile) {
+ super(indexFile, destFile);
sourceFile = new File(uri.getPath());
}
@@ -73,13 +73,6 @@ public class LocalFileDownloader extends Downloader {
return sourceFile.length();
}
- @Override
- public void download(long totalSize, @Nullable String sha256) throws IOException, InterruptedException {
- setFileSize(totalSize);
- setSha256(sha256);
- download();
- }
-
@Override
public void download() throws IOException, InterruptedException {
if (!sourceFile.exists()) {
diff --git a/app/src/main/java/org/fdroid/fdroid/net/TreeUriDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/TreeUriDownloader.java
index 2788ee594..830a7962f 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/TreeUriDownloader.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/TreeUriDownloader.java
@@ -1,9 +1,9 @@
package org.fdroid.fdroid.net;
-import android.annotation.TargetApi;
import android.content.Context;
import android.net.Uri;
+import org.fdroid.IndexFile;
import org.fdroid.download.Downloader;
import org.fdroid.download.NotFoundException;
import org.fdroid.fdroid.FDroidApp;
@@ -16,7 +16,6 @@ import java.io.InputStream;
import java.net.ProtocolException;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
/**
@@ -34,7 +33,6 @@ import androidx.documentfile.provider.DocumentFile;
* @see Open Files using Storage Access Framework
* @see Using Scoped Directory Access
*/
-@TargetApi(21)
public class TreeUriDownloader extends Downloader {
public static final String TAG = "TreeUriDownloader";
@@ -49,8 +47,8 @@ public class TreeUriDownloader extends Downloader {
private final Uri treeUri;
private final DocumentFile documentFile;
- TreeUriDownloader(Uri uri, File destFile) {
- super(destFile);
+ TreeUriDownloader(Uri uri, IndexFile indexFile, File destFile) {
+ super(indexFile, destFile);
context = FDroidApp.getInstance();
String path = uri.getEncodedPath();
int lastEscapedSlash = path.lastIndexOf(ESCAPED_SLASH);
@@ -102,14 +100,7 @@ public class TreeUriDownloader extends Downloader {
@Override
protected long totalDownloadSize() {
- return getFileSize() != null ? getFileSize() : documentFile.length();
- }
-
- @Override
- public void download(long totalSize, @Nullable String sha256) throws IOException, InterruptedException {
- setFileSize(totalSize);
- setSha256(sha256);
- downloadFromStream(false);
+ return getIndexFile().getSize() != null ? getIndexFile().getSize() : documentFile.length();
}
@Override
diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
index 1cdb5328f..0f17adbb8 100644
--- a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
+++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java
@@ -191,7 +191,7 @@ public class InstallConfirmActivity extends AppCompatActivity implements OnCance
TextView appName = (TextView) appSnippet.findViewById(R.id.app_name);
appName.setText(app.name);
ImageView appIcon = (ImageView) appSnippet.findViewById(R.id.app_icon);
- app.loadWithGlide(this, app.getIconPath(this))
+ app.loadWithGlide(this, app.iconFile)
.apply(Utils.getAlwaysShowIconRequestOptions())
.into(appIcon);
}
diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
index aa2ae0afc..e2f45dbc3 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
@@ -63,6 +63,7 @@ import org.fdroid.fdroid.privileged.views.AppDiff;
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
import org.fdroid.fdroid.views.appdetails.AntiFeaturesListingView;
import org.fdroid.fdroid.views.main.MainActivity;
+import org.fdroid.index.v2.FileV2;
import java.io.File;
import java.util.ArrayList;
@@ -148,8 +149,8 @@ public class AppDetailsRecyclerViewAdapter
compatibleVersionsDifferentSig.add(apk);
if (allowBySig) {
versions.add(apk);
- if (!versionsExpandTracker.containsKey(apk.apkName)) {
- versionsExpandTracker.put(apk.apkName, false);
+ if (!versionsExpandTracker.containsKey(apk.getApkPath())) {
+ versionsExpandTracker.put(apk.getApkPath(), false);
}
}
}
@@ -713,7 +714,7 @@ public class AppDetailsRecyclerViewAdapter
@Override
public void onScreenshotClick(int position) {
- ArrayList screenshots = Objects.requireNonNull(app).getAllScreenshots();
+ List screenshots = Objects.requireNonNull(app).getAllScreenshots();
context.startActivity(ScreenShotsActivity.getStartIntent(context, app.repoId, screenshots, position));
}
@@ -1104,7 +1105,8 @@ public class AppDetailsRecyclerViewAdapter
TextUtils.equals(apk.sig, app.installedSig);
boolean isApkSuggested = apk.equals(suggestedApk);
boolean isApkDownloading = callbacks.isAppDownloading() && downloadedApk != null &&
- downloadedApk.compareTo(apk) == 0 && TextUtils.equals(apk.apkName, downloadedApk.apkName);
+ downloadedApk.compareTo(apk) == 0 &&
+ TextUtils.equals(apk.getApkPath(), downloadedApk.getApkPath());
boolean isApkInstalledDummy = apk.versionCode == app.installedVersionCode &&
apk.compatible && apk.size == 0 && apk.maxSdkVersion == -1;
@@ -1198,7 +1200,7 @@ public class AppDetailsRecyclerViewAdapter
}
// Expand the view if it was previously expanded or when downloading
- expand(versionsExpandTracker.get(apk.apkName) || isApkDownloading);
+ expand(versionsExpandTracker.get(apk.getApkPath()) || isApkDownloading);
// Toggle expanded view when clicking the whole version item,
// unless it's an installed app version dummy item - it doesn't
@@ -1293,7 +1295,7 @@ public class AppDetailsRecyclerViewAdapter
}
private void expand(boolean expand) {
- versionsExpandTracker.put(apk.apkName, expand);
+ versionsExpandTracker.put(apk.getApkPath(), expand);
expandedLayout.setVisibility(expand ? View.VISIBLE : View.GONE);
versionCode.setVisibility(expand ? View.VISIBLE : View.GONE);
expandArrow.setImageDrawable(ContextCompat.getDrawable(context, expand ?
@@ -1314,7 +1316,7 @@ public class AppDetailsRecyclerViewAdapter
return;
}
- boolean expand = !versionsExpandTracker.get(apk.apkName);
+ boolean expand = !versionsExpandTracker.get(apk.getApkPath());
expand(expand);
if (expand) {
diff --git a/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsActivity.java b/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsActivity.java
index c0e24cb59..13ea5f72a 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsActivity.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsActivity.java
@@ -20,9 +20,10 @@ import androidx.viewpager.widget.ViewPager;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
+import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.App;
+import org.fdroid.index.v2.FileV2;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -41,11 +42,11 @@ public class ScreenShotsActivity extends AppCompatActivity {
private static boolean allowDownload = true;
- public static Intent getStartIntent(Context context, long repoId, ArrayList screenshots,
+ public static Intent getStartIntent(Context context, long repoId, List screenshots,
int startPosition) {
Intent intent = new Intent(context, ScreenShotsActivity.class);
intent.putExtra(EXTRA_REPO_ID, repoId);
- intent.putStringArrayListExtra(EXTRA_SCREENSHOT_LIST, screenshots);
+ intent.putStringArrayListExtra(EXTRA_SCREENSHOT_LIST, Utils.toString(screenshots));
intent.putExtra(EXTRA_START_POSITION, startPosition);
return intent;
}
@@ -59,7 +60,8 @@ public class ScreenShotsActivity extends AppCompatActivity {
setContentView(R.layout.activity_screenshots);
long repoId = getIntent().getLongExtra(EXTRA_REPO_ID, 1);
- List screenshots = getIntent().getStringArrayListExtra(EXTRA_SCREENSHOT_LIST);
+ List list = getIntent().getStringArrayListExtra(EXTRA_SCREENSHOT_LIST);
+ List screenshots = Utils.fileV2FromStrings(list);
int startPosition = getIntent().getIntExtra(EXTRA_START_POSITION, 0);
ViewPager viewPager = (ViewPager) findViewById(R.id.screenshot_view_pager);
@@ -86,9 +88,9 @@ public class ScreenShotsActivity extends AppCompatActivity {
private static class ScreenShotPagerAdapter extends FragmentStatePagerAdapter {
private final long repoId;
- private final List screenshots;
+ private final List screenshots;
- ScreenShotPagerAdapter(FragmentManager fragmentManager, long repoId, List screenshots) {
+ ScreenShotPagerAdapter(FragmentManager fragmentManager, long repoId, List screenshots) {
super(fragmentManager);
this.repoId = repoId;
this.screenshots = screenshots;
@@ -113,23 +115,23 @@ public class ScreenShotsActivity extends AppCompatActivity {
private static final String ARG_REPO_ID = "ARG_REPO_ID";
private static final String ARG_SCREENSHOT_URL = "ARG_SCREENSHOT_URL";
- static ScreenShotPageFragment newInstance(long repoId, @NonNull String screenshotUrl) {
+ static ScreenShotPageFragment newInstance(long repoId, @NonNull FileV2 screenshotUrl) {
ScreenShotPageFragment fragment = new ScreenShotPageFragment();
Bundle args = new Bundle();
args.putLong(ARG_REPO_ID, repoId);
- args.putString(ARG_SCREENSHOT_URL, screenshotUrl);
+ args.putString(ARG_SCREENSHOT_URL, screenshotUrl.serialize());
fragment.setArguments(args);
return fragment;
}
private long repoId;
- private String screenshotUrl;
+ private FileV2 screenshot;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
repoId = requireArguments().getLong(ARG_REPO_ID);
- screenshotUrl = requireArguments().getString(ARG_SCREENSHOT_URL);
+ screenshot = FileV2.deserialize(requireArguments().getString(ARG_SCREENSHOT_URL));
}
@Nullable
@@ -139,7 +141,7 @@ public class ScreenShotsActivity extends AppCompatActivity {
View rootView = inflater.inflate(R.layout.activity_screenshots_page, container, false);
ImageView screenshotView = (ImageView) rootView.findViewById(R.id.screenshot);
- App.loadWithGlide(requireContext(), repoId, screenshotUrl)
+ App.loadWithGlide(requireContext(), repoId, screenshot)
.onlyRetrieveFromCache(!allowDownload)
.error(R.drawable.screenshot_placeholder)
.fallback(R.drawable.screenshot_placeholder)
diff --git a/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsRecyclerViewAdapter.java
index a86d3da1b..10fa5d5f1 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsRecyclerViewAdapter.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/ScreenShotsRecyclerViewAdapter.java
@@ -12,6 +12,7 @@ import com.bumptech.glide.request.RequestOptions;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.App;
+import org.fdroid.index.v2.FileV2;
import java.util.List;
@@ -20,7 +21,7 @@ import java.util.List;
*/
class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter {
private final long repoId;
- private final List screenshots;
+ private final List screenshots;
private final RequestOptions displayImageOptions;
private final Listener listener;
diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java b/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java
index 300707434..684374ab4 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java
@@ -9,7 +9,6 @@ import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.annotation.ColorInt;
@@ -25,6 +24,7 @@ import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import org.fdroid.fdroid.R;
+import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.App;
import java.util.Random;
@@ -251,11 +251,10 @@ public class FeatureImage extends AppCompatImageView {
public void loadImageAndDisplay(App app) {
setColour(ContextCompat.getColor(getContext(), R.color.fdroid_blue));
- if (!TextUtils.isEmpty(app.featureGraphic)) {
- app.loadWithGlide(getContext(), app.featureGraphic).into(this);
+ if (app.featureGraphic == null) {
+ loadImageAndExtractColour(app.loadWithGlide(getContext(), app.iconFile));
} else {
- String path = app.getIconPath(getContext());
- loadImageAndExtractColour(app.loadWithGlide(getContext(), path));
+ Utils.loadWithGlide(getContext(), app.repoId, app.featureGraphic, this);
}
}
diff --git a/app/src/test/java/org/fdroid/fdroid/RepoUrlsTest.java b/app/src/test/java/org/fdroid/fdroid/RepoUrlsTest.java
index 76b33ad2f..b0c7c02dd 100644
--- a/app/src/test/java/org/fdroid/fdroid/RepoUrlsTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/RepoUrlsTest.java
@@ -20,6 +20,7 @@
package org.fdroid.fdroid;
import org.fdroid.fdroid.data.Apk;
+import org.fdroid.index.v2.FileV1;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -133,7 +134,7 @@ public class RepoUrlsTest {
public void testApkUrls() {
testReposWithFile(APK_NAME, tr -> {
Apk apk = new Apk();
- apk.apkName = APK_NAME;
+ apk.apkFile = new FileV1(APK_NAME, "hash", null, null);
apk.versionCode = 1;
apk.repoAddress = tr.repoUrl;
apk.canonicalRepoAddress = tr.repoUrl;
diff --git a/app/src/test/java/org/fdroid/fdroid/TestUtils.java b/app/src/test/java/org/fdroid/fdroid/TestUtils.java
index 2ab6ad391..f7887a4b3 100644
--- a/app/src/test/java/org/fdroid/fdroid/TestUtils.java
+++ b/app/src/test/java/org/fdroid/fdroid/TestUtils.java
@@ -2,6 +2,7 @@ package org.fdroid.fdroid;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.App;
+import org.fdroid.index.v2.FileV1;
import java.io.File;
import java.io.FileOutputStream;
@@ -41,20 +42,19 @@ public class TestUtils {
}
}
- public static Apk getApk(long appId, int versionCode) {
- return getApk(appId, versionCode, "signature", null);
+ public static Apk getApk(int versionCode) {
+ return getApk(versionCode, "signature", null);
}
- public static Apk getApk(long appId, int versionCode, String signature, String releaseChannel) {
+ public static Apk getApk(int versionCode, String signature, String releaseChannel) {
Apk apk = new Apk();
- apk.appId = appId;
apk.repoAddress = "http://www.example.com/fdroid/repo";
apk.canonicalRepoAddress = "http://www.example.com/fdroid/repo";
apk.versionCode = versionCode;
apk.repoId = 1;
apk.versionName = "The good one";
apk.hash = "11111111aaaaaaaa";
- apk.apkName = "Test Apk";
+ apk.apkFile = new FileV1("Test Apk", "hash", null, null);
apk.size = 10000;
apk.compatible = true;
apk.sig = signature;
diff --git a/app/src/test/java/org/fdroid/fdroid/data/ApkTest.java b/app/src/test/java/org/fdroid/fdroid/data/ApkTest.java
index 9ec5c0dc5..a98b6efcb 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/ApkTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/ApkTest.java
@@ -7,6 +7,7 @@ import android.webkit.MimeTypeMap;
import org.apache.commons.io.FileUtils;
import org.fdroid.fdroid.installer.ApkCache;
import org.fdroid.fdroid.nearby.PublicSourceDirProvider;
+import org.fdroid.index.v2.FileV1;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,6 +18,7 @@ import org.robolectric.shadows.ShadowMimeTypeMap;
import java.io.File;
import java.io.IOException;
+import java.net.URL;
import androidx.test.core.app.ApplicationProvider;
@@ -41,7 +43,7 @@ public class ApkTest {
@Test(expected = IllegalStateException.class)
public void testGetMediaInstallPathWithApk() {
Apk apk = new Apk();
- apk.apkName = "test.apk";
+ apk.apkFile = new FileV1("test.apk", "hash", null, null);
apk.repoAddress = "https://example.com/fdroid/repo";
apk.canonicalRepoAddress = "https://example.com/fdroid/repo";
assertTrue(apk.isApk());
@@ -51,7 +53,7 @@ public class ApkTest {
@Test
public void testGetMediaInstallPathWithOta() throws IOException {
Apk apk = new Apk();
- apk.apkName = "org.fdroid.fdroid.privileged.ota_2110.zip";
+ apk.apkFile = new FileV1("org.fdroid.fdroid.privileged.ota_2110.zip", "hash", null, null);
apk.repoAddress = "https://example.com/fdroid/repo";
apk.canonicalRepoAddress = "https://example.com/fdroid/repo";
assertFalse(apk.isApk());
@@ -63,7 +65,7 @@ public class ApkTest {
@Test
public void testGetMediaInstallPathWithObf() {
Apk apk = new Apk();
- apk.apkName = "Norway_bouvet_europe_2.obf";
+ apk.apkFile = new FileV1("Norway_bouvet_europe_2.obf", "hash", null, null);
apk.repoAddress = "https://example.com/fdroid/repo";
apk.canonicalRepoAddress = "https://example.com/fdroid/repo";
assertFalse(apk.isApk());
@@ -74,7 +76,7 @@ public class ApkTest {
@Test
public void testGetMediaInstallPathWithObfZip() throws IOException {
Apk apk = new Apk();
- apk.apkName = "Norway_bouvet_europe_2.obf.zip";
+ apk.apkFile = new FileV1("Norway_bouvet_europe_2.obf.zip", "hash", null, null);
apk.repoAddress = "https://example.com/fdroid/repo";
apk.canonicalRepoAddress = "https://example.com/fdroid/repo";
assertFalse(apk.isApk());
@@ -84,7 +86,8 @@ public class ApkTest {
}
private void copyResourceFileToCache(Apk apk) throws IOException {
- FileUtils.copyInputStreamToFile(getClass().getClassLoader().getResource(apk.apkName).openStream(),
+ URL res = getClass().getClassLoader().getResource(apk.apkFile.getName());
+ FileUtils.copyInputStreamToFile(res.openStream(),
ApkCache.getApkDownloadPath(context, apk.getCanonicalUrl()));
}
}
diff --git a/app/src/test/java/org/fdroid/fdroid/data/SuggestedVersionTest.java b/app/src/test/java/org/fdroid/fdroid/data/SuggestedVersionTest.java
index a3adffb13..af73be714 100644
--- a/app/src/test/java/org/fdroid/fdroid/data/SuggestedVersionTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/data/SuggestedVersionTest.java
@@ -38,9 +38,9 @@ public class SuggestedVersionTest {
App singleApp = TestUtils.getApp();
singleApp.installedVersionCode = 1;
singleApp.installedSig = TestUtils.FDROID_SIG;
- Apk apk1 = TestUtils.getApk(singleApp.getId(), 1, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk2 = TestUtils.getApk(singleApp.getId(), 2, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk3 = TestUtils.getApk(singleApp.getId(), 3, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_BETA);
+ Apk apk1 = TestUtils.getApk(1, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk2 = TestUtils.getApk(2, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk3 = TestUtils.getApk(3, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_BETA);
List apks = new ArrayList<>();
apks.add(apk3);
apks.add(apk2);
@@ -57,11 +57,11 @@ public class SuggestedVersionTest {
App singleApp = TestUtils.getApp();
singleApp.installedVersionCode = 0;
- Apk apk1 = TestUtils.getApk(singleApp.getId(), 1, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk2 = TestUtils.getApk(singleApp.getId(), 2, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk3 = TestUtils.getApk(singleApp.getId(), 3, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk4 = TestUtils.getApk(singleApp.getId(), 4, TestUtils.UPSTREAM_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk5 = TestUtils.getApk(singleApp.getId(), 5, TestUtils.UPSTREAM_SIG, Apk.RELEASE_CHANNEL_BETA);
+ Apk apk1 = TestUtils.getApk(1, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk2 = TestUtils.getApk(2, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk3 = TestUtils.getApk(3, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk4 = TestUtils.getApk(4, TestUtils.UPSTREAM_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk5 = TestUtils.getApk(5, TestUtils.UPSTREAM_SIG, Apk.RELEASE_CHANNEL_BETA);
List apks = new ArrayList<>();
apks.add(apk5);
apks.add(apk4);
@@ -80,8 +80,8 @@ public class SuggestedVersionTest {
assertSuggested(singleApp, apks, 3, Apk.RELEASE_CHANNEL_STABLE);
// This adds the "suggestedVersionCode" version of the app, but signed by f-droid.
- Apk apk4f = TestUtils.getApk(singleApp.getId(), 4, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
- Apk apk5f = TestUtils.getApk(singleApp.getId(), 5, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_BETA);
+ Apk apk4f = TestUtils.getApk(4, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_STABLE);
+ Apk apk5f = TestUtils.getApk(5, TestUtils.FDROID_SIG, Apk.RELEASE_CHANNEL_BETA);
apks.clear();
apks.add(apk5);
apks.add(apk5f);
diff --git a/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java b/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java
index 3512d32fe..fb6d6f720 100644
--- a/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java
@@ -4,6 +4,7 @@ import android.content.ContextWrapper;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.data.Apk;
+import org.fdroid.index.v2.FileV1;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,7 +18,6 @@ import static org.junit.Assert.assertFalse;
@RunWith(RobolectricTestRunner.class)
public class FileInstallerTest {
- public static final String TAG = "FileInstallerTest";
private ContextWrapper context;
@@ -31,7 +31,7 @@ public class FileInstallerTest {
@Test
public void testInstallOtaZip() {
Apk apk = new Apk();
- apk.apkName = "org.fdroid.fdroid.privileged.ota_2010.zip";
+ apk.apkFile = new FileV1("org.fdroid.fdroid.privileged.ota_2010.zip", "hash", null, null);
apk.packageName = "org.fdroid.fdroid.privileged.ota";
apk.versionCode = 2010;
assertFalse(apk.isApk());
diff --git a/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java b/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java
index cca65c351..8265bfd80 100644
--- a/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java
@@ -4,6 +4,7 @@ import android.content.ContextWrapper;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.data.Apk;
+import org.fdroid.index.v2.FileV1;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,7 +29,7 @@ public class InstallerFactoryTest {
public void testApkInstallerInstance() {
for (String filename : new String[]{"test.apk", "A.APK", "b.ApK"}) {
Apk apk = new Apk();
- apk.apkName = filename;
+ apk.apkFile = new FileV1(filename, "hash", null, null);
apk.packageName = "test";
Installer installer = InstallerFactory.create(context, apk);
assertEquals(filename + " should use a DefaultInstaller",
@@ -41,7 +42,7 @@ public class InstallerFactoryTest {
public void testFileInstallerInstance() {
for (String filename : new String[]{"org.fdroid.fdroid.privileged.ota_2110.zip", "test.ZIP"}) {
Apk apk = new Apk();
- apk.apkName = filename;
+ apk.apkFile = new FileV1(filename, "hash", null, null);
apk.packageName = "cafe0088";
Installer installer = InstallerFactory.create(context, apk);
assertEquals("should be a FileInstaller",
diff --git a/app/src/test/java/org/fdroid/fdroid/views/AppDetailsAdapterTest.java b/app/src/test/java/org/fdroid/fdroid/views/AppDetailsAdapterTest.java
index 9d0ce90b8..7d54cd2d8 100644
--- a/app/src/test/java/org/fdroid/fdroid/views/AppDetailsAdapterTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/views/AppDetailsAdapterTest.java
@@ -17,6 +17,7 @@ import org.fdroid.fdroid.R;
import org.fdroid.fdroid.TestUtils;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.App;
+import org.fdroid.index.v2.FileV2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,7 +58,9 @@ public class AppDetailsAdapterTest {
@Test
public void appWithScreenshots() {
App app = TestUtils.getApp();
- app.phoneScreenshots = new String[]{"screenshot1.png", "screenshot2.png"};
+ app.phoneScreenshots = new ArrayList<>(2);
+ app.phoneScreenshots.add(FileV2.fromPath("screenshot1.png"));
+ app.phoneScreenshots.add(FileV2.fromPath("screenshot2.png"));
AppDetailsRecyclerViewAdapter adapter = new AppDetailsRecyclerViewAdapter(context, app, dummyCallbacks);
adapter.updateItems(app, Collections.emptyList(), appPrefs);
@@ -71,9 +74,9 @@ public class AppDetailsAdapterTest {
App app = TestUtils.getApp();
app.preferredSigner = "eaa1d713b9c2a0475234a86d6539f910";
List apks = new ArrayList<>();
- apks.add(TestUtils.getApk(app.getId(), 1));
- apks.add(TestUtils.getApk(app.getId(), 2));
- apks.add(TestUtils.getApk(app.getId(), 3));
+ apks.add(TestUtils.getApk(1));
+ apks.add(TestUtils.getApk(2));
+ apks.add(TestUtils.getApk(3));
app.installedApk = apks.get(0);
AppDetailsRecyclerViewAdapter adapter = new AppDetailsRecyclerViewAdapter(context, app, dummyCallbacks);