diff --git a/res/values/strings.xml b/res/values/strings.xml
index b4069ef33..ac9310003 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -128,4 +128,8 @@
Database sync mode
Set the value of SQLite\'s "synchronous" flag
+
+ Application compatibility
+ Incompatible apps
+ Show apps written for newer Android versions or different hardware
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 4a5c09be7..0a86e4bc3 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -33,6 +33,11 @@
android:defaultValue="false" android:summary="@string/antinonfreenetlong"
android:key="antiNonFreeNet" />
+
+
+
diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java
index 4496489aa..ecb6b6dee 100644
--- a/src/org/fdroid/fdroid/AppDetails.java
+++ b/src/org/fdroid/fdroid/AppDetails.java
@@ -70,10 +70,8 @@ public class AppDetails extends ListActivity {
private class ApkListAdapter extends BaseAdapter {
private List items = new ArrayList();
- private DB.Apk.CompatibilityChecker compatChecker;
public ApkListAdapter(Context context) {
- compatChecker = DB.Apk.CompatibilityChecker.getChecker(context);
}
public void addItem(DB.Apk apk) {
@@ -160,6 +158,7 @@ public class AppDetails extends ListActivity {
private String appid;
private PackageManager mPm;
private ProgressDialog pd;
+ private DB.Apk.CompatibilityChecker compatChecker;
private Context mctx = this;
@@ -200,6 +199,7 @@ public class AppDetails extends ListActivity {
pref_cacheDownloaded = prefs.getBoolean("cacheDownloaded", true);
pref_expert = prefs.getBoolean("expert", false);
viewResetRequired = true;
+ compatChecker = DB.Apk.CompatibilityChecker.getChecker(this);
}
@@ -295,11 +295,14 @@ public class AppDetails extends ListActivity {
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
+ curapk = app.apks.get(position);
+
+ // Ignore attempt to install incompatible APK
+ if (!compatChecker.isCompatible(curapk)) return;
+
// Create alert dialog...
final AlertDialog p = new AlertDialog.Builder(this).create();
- curapk = app.apks.get(position);
-
// Set the title and icon...
String icon_path = DB.getIconsPath() + app.icon;
File test_icon = new File(icon_path);
diff --git a/src/org/fdroid/fdroid/DB.java b/src/org/fdroid/fdroid/DB.java
index 48e41873a..1d0d2d83f 100644
--- a/src/org/fdroid/fdroid/DB.java
+++ b/src/org/fdroid/fdroid/DB.java
@@ -217,9 +217,11 @@ public class DB {
public boolean isCompatible(Apk apk) {
if (apk.minSdkVersion > SDK_INT)
return false;
- for (String feat : apk.features) {
- if (!pm.hasSystemFeature(feat))
- return false;
+ if (apk.features != null) {
+ for (String feat : apk.features) {
+ if (!pm.hasSystemFeature(feat))
+ return false;
+ }
}
return true;
}
@@ -323,6 +325,7 @@ public class DB {
private PackageManager mPm;
private Context mContext;
+ private Apk.CompatibilityChecker compatChecker;
public DB(Context ctx) {
@@ -343,6 +346,7 @@ public class DB {
sync_mode = null;
if (sync_mode != null)
Log.d("FDroid", "Database synchronization mode: " + sync_mode);
+ compatChecker = Apk.CompatibilityChecker.getChecker(ctx);
}
public void close() {
@@ -374,8 +378,9 @@ public class DB {
return count;
}
- // Return a list of apps matching the given criteria. Filtering is also
- // done based on the user's current anti-features preferences.
+ // Return a list of apps matching the given criteria. Filtering is
+ // also done based on compatibility and anti-features according to
+ // the user's current preferences.
// 'appid' - specific app id to retrieve, or null
// 'filter' - search text to filter on, or null
// 'update' - update installed version information from device, rather than
@@ -388,6 +393,7 @@ public class DB {
boolean pref_antiTracking = prefs.getBoolean("antiTracking", false);
boolean pref_antiNonFreeAdd = prefs.getBoolean("antiNonFreeAdd", false);
boolean pref_antiNonFreeNet = prefs.getBoolean("antiNonFreeNet", false);
+ boolean pref_showIncompat = prefs.getBoolean("showIncompatible", false);
Vector result = new Vector();
Cursor c = null;
@@ -453,6 +459,7 @@ public class DB {
+ " where id = ? order by vercode desc",
new String[] { app.id });
c2.moveToFirst();
+ boolean compatible = pref_showIncompat;
while (!c2.isAfterLast()) {
Apk apk = new Apk();
apk.id = app.id;
@@ -475,11 +482,21 @@ public class DB {
apk.features = decodeList(c2.getString(c2
.getColumnIndex("features")));
app.apks.add(apk);
+ if (!compatible && compatChecker.isCompatible(apk)) {
+ // At least one compatible APK.
+ compatible = true;
+ }
c2.moveToNext();
}
c2.close();
- result.add(app);
+ if (compatible) {
+ result.add(app);
+ }
+ else {
+ Log.d("FDroid", "Excluding incompatible application: "
+ + app.id);
+ }
}
c.moveToNext();
diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java
index 3385ce371..1f04f183e 100644
--- a/src/org/fdroid/fdroid/FDroid.java
+++ b/src/org/fdroid/fdroid/FDroid.java
@@ -309,6 +309,7 @@ public class FDroid extends TabActivity implements OnItemClickListener {
apps_av.clear();
apps_up.clear();
+ long startTime = System.currentTimeMillis();
Vector apps = db.getApps(null, null, update);
if (apps.isEmpty()) {
// Don't attempt this more than once - we may have invalid
@@ -322,7 +323,9 @@ public class FDroid extends TabActivity implements OnItemClickListener {
triedEmptyUpdate = true;
return;
}
- Log.d("FDroid", "Updating lists - " + apps.size() + " apps in total");
+ Log.d("FDroid", "Updating lists - " + apps.size() + " apps in total"
+ + " (update took " + (System.currentTimeMillis() - startTime)
+ + " ms)");
for (DB.App app : apps) {
if (app.installedVersion == null) {