Add support for filtering apk compatibility by maxSdkVersion

For now it's enforced like minSdkVersion. It is possible to try and install
incompatible apks by enabling "Incompatible Versions" and agreeing to the
warning shown when clicking on such a version.
This commit is contained in:
Daniel Martí 2014-02-19 18:11:32 +01:00
parent dc1bdc2f3b
commit e6ec5ee242
8 changed files with 39 additions and 10 deletions

View File

@ -200,7 +200,9 @@
<string name="repo_disabled_notification">Disabled "%1$s".\n\nYou will <string name="repo_disabled_notification">Disabled "%1$s".\n\nYou will
need to re-enable this repository to install apps from it. need to re-enable this repository to install apps from it.
</string> </string>
<string name="minsdk_or_later">Android %s or later</string> <string name="minsdk_or_later">%s or later</string>
<string name="up_to_maxsdk">up to %s</string>
<string name="minsdk_up_to_maxsdk">%1$s up to %2$s</string>
<string name="not_on_same_wifi">Your device is not on the same WiFi as the local repo you just added! Try joining this network: %s</string> <string name="not_on_same_wifi">Your device is not on the same WiFi as the local repo you just added! Try joining this network: %s</string>
<string name="requires_features">Requires: %1$s</string> <string name="requires_features">Requires: %1$s</string>

View File

@ -145,12 +145,21 @@ public class AppDetails extends ListActivity {
holder.size.setVisibility(View.GONE); holder.size.setVisibility(View.GONE);
} }
if (pref_expert && apk.minSdkVersion > 0) { if (!pref_expert) {
holder.api.setVisibility(View.GONE);
} else if (apk.minSdkVersion > 0 && apk.maxSdkVersion > 0) {
holder.api.setText(getString(R.string.minsdk_up_to_maxsdk,
Utils.getAndroidVersionName(apk.minSdkVersion),
Utils.getAndroidVersionName(apk.maxSdkVersion)));
holder.api.setVisibility(View.VISIBLE);
} else if (apk.minSdkVersion > 0) {
holder.api.setText(getString(R.string.minsdk_or_later, holder.api.setText(getString(R.string.minsdk_or_later,
Utils.getAndroidVersionName(apk.minSdkVersion))); Utils.getAndroidVersionName(apk.minSdkVersion)));
holder.api.setVisibility(View.VISIBLE); holder.api.setVisibility(View.VISIBLE);
} else { } else if (apk.maxSdkVersion > 0) {
holder.api.setVisibility(View.GONE); holder.api.setText(getString(R.string.up_to_maxsdk,
Utils.getAndroidVersionName(apk.maxSdkVersion)));
holder.api.setVisibility(View.VISIBLE);
} }
if (apk.srcname != null) { if (apk.srcname != null) {

View File

@ -69,7 +69,7 @@ public class CompatibilityChecker extends Compatibility {
List<String> incompatibleReasons = new ArrayList<String>(); List<String> incompatibleReasons = new ArrayList<String>();
if (!hasApi(apk.minSdkVersion)) { if (!hasApi(apk.minSdkVersion) || !upToApi(apk.maxSdkVersion)) {
incompatibleReasons.add( incompatibleReasons.add(
context.getResources().getString( context.getResources().getString(
R.string.minsdk_or_later, R.string.minsdk_or_later,

View File

@ -158,6 +158,12 @@ public class RepoXMLHandler extends DefaultHandler {
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
curapk.minSdkVersion = 0; curapk.minSdkVersion = 0;
} }
} else if (curel.equals("maxsdkver")) {
try {
curapk.maxSdkVersion = Integer.parseInt(str);
} catch (NumberFormatException ex) {
curapk.maxSdkVersion = 0;
}
} else if (curel.equals("added")) { } else if (curel.equals("added")) {
try { try {
curapk.added = str.length() == 0 ? null : Utils.DATE_FORMAT curapk.added = str.length() == 0 ? null : Utils.DATE_FORMAT

View File

@ -4,10 +4,16 @@ import android.os.Build;
public abstract class Compatibility { public abstract class Compatibility {
// like minSdkVersion
protected static boolean hasApi(int apiLevel) { protected static boolean hasApi(int apiLevel) {
return getApi() >= apiLevel; return getApi() >= apiLevel;
} }
// like maxSdkVersion
protected static boolean upToApi(int apiLevel) {
return (apiLevel < 1 || getApi() <= apiLevel);
}
protected static int getApi() { protected static int getApi() {
return Build.VERSION.SDK_INT; return Build.VERSION.SDK_INT;
} }

View File

@ -16,6 +16,7 @@ public class Apk extends ValueObject implements Comparable<Apk> {
public String hash; public String hash;
public String hashType; public String hashType;
public int minSdkVersion; // 0 if unknown public int minSdkVersion; // 0 if unknown
public int maxSdkVersion; // 0 if none
public Date added; public Date added;
public Utils.CommaSeparatedList permissions; // null if empty or public Utils.CommaSeparatedList permissions; // null if empty or
// unknown // unknown
@ -75,6 +76,8 @@ public class Apk extends ValueObject implements Comparable<Apk> {
compatible = cursor.getInt(i) == 1; compatible = cursor.getInt(i) == 1;
} else if (column.equals(ApkProvider.DataColumns.MIN_SDK_VERSION)) { } else if (column.equals(ApkProvider.DataColumns.MIN_SDK_VERSION)) {
minSdkVersion = cursor.getInt(i); minSdkVersion = cursor.getInt(i);
} else if (column.equals(ApkProvider.DataColumns.MAX_SDK_VERSION)) {
maxSdkVersion = cursor.getInt(i);
} else if (column.equals(ApkProvider.DataColumns.NAME)) { } else if (column.equals(ApkProvider.DataColumns.NAME)) {
apkName = cursor.getString(i); apkName = cursor.getString(i);
} else if (column.equals(ApkProvider.DataColumns.PERMISSIONS)) { } else if (column.equals(ApkProvider.DataColumns.PERMISSIONS)) {
@ -121,6 +124,7 @@ public class Apk extends ValueObject implements Comparable<Apk> {
values.put(ApkProvider.DataColumns.SIZE, size); values.put(ApkProvider.DataColumns.SIZE, size);
values.put(ApkProvider.DataColumns.NAME, apkName); values.put(ApkProvider.DataColumns.NAME, apkName);
values.put(ApkProvider.DataColumns.MIN_SDK_VERSION, minSdkVersion); values.put(ApkProvider.DataColumns.MIN_SDK_VERSION, minSdkVersion);
values.put(ApkProvider.DataColumns.MAX_SDK_VERSION, maxSdkVersion);
values.put(ApkProvider.DataColumns.ADDED_DATE, added == null ? "" : Utils.DATE_FORMAT.format(added)); values.put(ApkProvider.DataColumns.ADDED_DATE, added == null ? "" : Utils.DATE_FORMAT.format(added));
values.put(ApkProvider.DataColumns.PERMISSIONS, Utils.CommaSeparatedList.str(permissions)); values.put(ApkProvider.DataColumns.PERMISSIONS, Utils.CommaSeparatedList.str(permissions));
values.put(ApkProvider.DataColumns.FEATURES, Utils.CommaSeparatedList.str(features)); values.put(ApkProvider.DataColumns.FEATURES, Utils.CommaSeparatedList.str(features));

View File

@ -149,6 +149,7 @@ public class ApkProvider extends FDroidProvider {
public static String SIGNATURE = "sig"; public static String SIGNATURE = "sig";
public static String SOURCE_NAME = "srcname"; public static String SOURCE_NAME = "srcname";
public static String MIN_SDK_VERSION = "minSdkVersion"; public static String MIN_SDK_VERSION = "minSdkVersion";
public static String MAX_SDK_VERSION = "maxSdkVersion";
public static String PERMISSIONS = "permissions"; public static String PERMISSIONS = "permissions";
public static String FEATURES = "features"; public static String FEATURES = "features";
public static String NATIVE_CODE = "nativecode"; public static String NATIVE_CODE = "nativecode";
@ -161,9 +162,9 @@ public class ApkProvider extends FDroidProvider {
public static String[] ALL = { public static String[] ALL = {
_ID, APK_ID, VERSION, REPO_ID, HASH, VERSION_CODE, NAME, SIZE, _ID, APK_ID, VERSION, REPO_ID, HASH, VERSION_CODE, NAME, SIZE,
SIGNATURE, SOURCE_NAME, MIN_SDK_VERSION, PERMISSIONS, FEATURES, SIGNATURE, SOURCE_NAME, MIN_SDK_VERSION, MAX_SDK_VERSION,
NATIVE_CODE, HASH_TYPE, ADDED_DATE, IS_COMPATIBLE, PERMISSIONS, FEATURES, NATIVE_CODE, HASH_TYPE, ADDED_DATE,
REPO_VERSION, REPO_ADDRESS, INCOMPATIBLE_REASONS IS_COMPATIBLE, REPO_VERSION, REPO_ADDRESS, INCOMPATIBLE_REASONS
}; };
} }

View File

@ -46,6 +46,7 @@ public class DBHelper extends SQLiteOpenHelper {
+ "sig string, " + "sig string, "
+ "srcname string, " + "srcname string, "
+ "minSdkVersion integer, " + "minSdkVersion integer, "
+ "maxSdkVersion integer, "
+ "permissions string, " + "permissions string, "
+ "features string, " + "features string, "
+ "nativecode string, " + "nativecode string, "
@ -86,7 +87,7 @@ public class DBHelper extends SQLiteOpenHelper {
+ "iconUrl text, " + "iconUrl text, "
+ "primary key(id));"; + "primary key(id));";
private static final int DB_VERSION = 39; private static final int DB_VERSION = 40;
private Context context; private Context context;