Performence improvements, work in progress
This commit is contained in:
parent
003d65627e
commit
0efc4c6794
@ -37,9 +37,6 @@
|
|||||||
android:key="antiNonFreeDep" />
|
android:key="antiNonFreeDep" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/appcompatibility">
|
<PreferenceCategory android:title="@string/appcompatibility">
|
||||||
<CheckBoxPreference android:title="@string/showincompat"
|
|
||||||
android:defaultValue="false" android:summary="@string/showincompat_long"
|
|
||||||
android:key="showIncompatible" />
|
|
||||||
<CheckBoxPreference android:title="@string/rooted"
|
<CheckBoxPreference android:title="@string/rooted"
|
||||||
android:defaultValue="true" android:summary="@string/rooted_long"
|
android:defaultValue="true" android:summary="@string/rooted_long"
|
||||||
android:key="rooted" />
|
android:key="rooted" />
|
||||||
|
@ -22,8 +22,7 @@ import java.io.File;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
import org.fdroid.fdroid.DB.Apk.CompatibilityChecker;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
@ -130,12 +129,6 @@ public class AppDetails extends ListActivity {
|
|||||||
} else {
|
} else {
|
||||||
added.setVisibility(View.GONE);
|
added.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
if (!compatChecker.isCompatible(apk)) {
|
|
||||||
View[] views = { v, version, status, size, buildtype, added };
|
|
||||||
for (View view : views) {
|
|
||||||
view.setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +156,6 @@ public class AppDetails extends ListActivity {
|
|||||||
private int app_currentvercode;
|
private int app_currentvercode;
|
||||||
private DB.Apk curapk;
|
private DB.Apk curapk;
|
||||||
private String appid;
|
private String appid;
|
||||||
private CompatibilityChecker compatChecker;
|
|
||||||
private PackageManager mPm;
|
private PackageManager mPm;
|
||||||
private DownloadHandler downloadHandler;
|
private DownloadHandler downloadHandler;
|
||||||
private boolean stateRetained;
|
private boolean stateRetained;
|
||||||
@ -217,15 +209,6 @@ public class AppDetails extends ListActivity {
|
|||||||
if (viewResetRequired) {
|
if (viewResetRequired) {
|
||||||
reset();
|
reset();
|
||||||
viewResetRequired = false;
|
viewResetRequired = false;
|
||||||
} else {
|
|
||||||
// Doing the reset() will usually get our compatChecker, but if
|
|
||||||
// we're skipping that we'd better get one now...
|
|
||||||
try {
|
|
||||||
DB db = DB.getDB();
|
|
||||||
compatChecker = db.getCompatibilityChecker();
|
|
||||||
} finally {
|
|
||||||
DB.releaseDB();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (downloadHandler != null) {
|
if (downloadHandler != null) {
|
||||||
downloadHandler.startUpdates();
|
downloadHandler.startUpdates();
|
||||||
@ -280,16 +263,22 @@ public class AppDetails extends ListActivity {
|
|||||||
// Reset the display and list contents. Used when entering the activity, and
|
// Reset the display and list contents. Used when entering the activity, and
|
||||||
// also when something has been installed/uninstalled.
|
// also when something has been installed/uninstalled.
|
||||||
private void reset() {
|
private void reset() {
|
||||||
|
|
||||||
Log.d("FDroid", "Getting application details for " + appid);
|
Log.d("FDroid", "Getting application details for " + appid);
|
||||||
DB.Apk curver;
|
app = null;
|
||||||
try {
|
Vector<DB.App> apps = ((FDroidApp) getApplication()).getApps();
|
||||||
DB db = DB.getDB();
|
for (DB.App tapp : apps) {
|
||||||
compatChecker = db.getCompatibilityChecker();
|
if (tapp.id.equals(appid)) {
|
||||||
app = db.getApps(appid, null, true, false).get(0);
|
app = tapp;
|
||||||
curver = app.getCurrentVersion(compatChecker);
|
break;
|
||||||
} finally {
|
}
|
||||||
DB.releaseDB();
|
|
||||||
}
|
}
|
||||||
|
if (app == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Apk curver = app.getCurrentVersion();
|
||||||
app_currentvercode = curver == null ? 0 : curver.vercode;
|
app_currentvercode = curver == null ? 0 : curver.vercode;
|
||||||
|
|
||||||
// Get the signature of the installed package...
|
// Get the signature of the installed package...
|
||||||
@ -359,7 +348,7 @@ public class AppDetails extends ListActivity {
|
|||||||
if (app.installedVersion != null
|
if (app.installedVersion != null
|
||||||
&& app.installedVersion.equals(curapk.version)) {
|
&& app.installedVersion.equals(curapk.version)) {
|
||||||
removeApk(app.id);
|
removeApk(app.id);
|
||||||
} else if (compatChecker.isCompatible(curapk)) {
|
} else {
|
||||||
install();
|
install();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +358,7 @@ public class AppDetails extends ListActivity {
|
|||||||
|
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onCreateOptionsMenu(menu);
|
||||||
menu.clear();
|
menu.clear();
|
||||||
DB.Apk curver = app.getCurrentVersion(compatChecker);
|
DB.Apk curver = app.getCurrentVersion();
|
||||||
if (app.installedVersion != null && curver != null
|
if (app.installedVersion != null && curver != null
|
||||||
&& !app.installedVersion.equals(curver.version)) {
|
&& !app.installedVersion.equals(curver.version)) {
|
||||||
menu.add(Menu.NONE, INSTALL, 0, R.string.menu_update).setIcon(
|
menu.add(Menu.NONE, INSTALL, 0, R.string.menu_update).setIcon(
|
||||||
@ -413,7 +402,7 @@ public class AppDetails extends ListActivity {
|
|||||||
|
|
||||||
case INSTALL:
|
case INSTALL:
|
||||||
// Note that this handles updating as well as installing.
|
// Note that this handles updating as well as installing.
|
||||||
curapk = app.getCurrentVersion(compatChecker);
|
curapk = app.getCurrentVersion();
|
||||||
if (curapk != null)
|
if (curapk != null)
|
||||||
install();
|
install();
|
||||||
return true;
|
return true;
|
||||||
@ -480,6 +469,8 @@ public class AppDetails extends ListActivity {
|
|||||||
Uri uri = Uri.fromParts("package", pkginfo.packageName, null);
|
Uri uri = Uri.fromParts("package", pkginfo.packageName, null);
|
||||||
Intent intent = new Intent(Intent.ACTION_DELETE, uri);
|
Intent intent = new Intent(Intent.ACTION_DELETE, uri);
|
||||||
startActivityForResult(intent, REQUEST_UNINSTALL);
|
startActivityForResult(intent, REQUEST_UNINSTALL);
|
||||||
|
((FDroidApp) getApplication()).invalidateApps();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installApk(String file) {
|
private void installApk(String file) {
|
||||||
@ -488,6 +479,7 @@ public class AppDetails extends ListActivity {
|
|||||||
intent.setDataAndType(Uri.parse("file://" + file),
|
intent.setDataAndType(Uri.parse("file://" + file),
|
||||||
"application/vnd.android.package-archive");
|
"application/vnd.android.package-archive");
|
||||||
startActivityForResult(intent, REQUEST_INSTALL);
|
startActivityForResult(intent, REQUEST_INSTALL);
|
||||||
|
((FDroidApp) getApplication()).invalidateApps();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgressDialog createProgressDialog(String file, int p, int max) {
|
private ProgressDialog createProgressDialog(String file, int p, int max) {
|
||||||
|
74
src/org/fdroid/fdroid/AppFilter.java
Normal file
74
src/org/fdroid/fdroid/AppFilter.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
public class AppFilter {
|
||||||
|
|
||||||
|
boolean pref_antiAds;
|
||||||
|
boolean pref_antiTracking;
|
||||||
|
boolean pref_antiNonFreeAdd;
|
||||||
|
boolean pref_antiNonFreeNet;
|
||||||
|
boolean pref_antiNonFreeDep;
|
||||||
|
boolean pref_rooted;
|
||||||
|
|
||||||
|
public AppFilter(Context ctx) {
|
||||||
|
|
||||||
|
// Read preferences and cache them so we can do quick lookups.
|
||||||
|
SharedPreferences prefs = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(ctx);
|
||||||
|
pref_antiAds = prefs.getBoolean("antiAds", false);
|
||||||
|
pref_antiTracking = prefs.getBoolean("antiTracking", false);
|
||||||
|
pref_antiNonFreeAdd = prefs.getBoolean("antiNonFreeAdd", false);
|
||||||
|
pref_antiNonFreeNet = prefs.getBoolean("antiNonFreeNet", false);
|
||||||
|
pref_antiNonFreeDep = prefs.getBoolean("antiNonFreeDep", false);
|
||||||
|
pref_rooted = prefs.getBoolean("rooted", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if the given app should be filtered based on user
|
||||||
|
// preferences, and false otherwise.
|
||||||
|
public boolean filter(DB.App app) {
|
||||||
|
boolean filtered = false;
|
||||||
|
if (app.antiFeatures != null) {
|
||||||
|
for (String af : app.antiFeatures) {
|
||||||
|
if (af.equals("Ads") && !pref_antiAds)
|
||||||
|
filtered = true;
|
||||||
|
else if (af.equals("Tracking") && !pref_antiTracking)
|
||||||
|
filtered = true;
|
||||||
|
else if (af.equals("NonFreeNet") && !pref_antiNonFreeNet)
|
||||||
|
filtered = true;
|
||||||
|
else if (af.equals("NonFreeAdd") && !pref_antiNonFreeAdd)
|
||||||
|
filtered = true;
|
||||||
|
else if (af.equals("NonFreeDep") && !pref_antiNonFreeDep)
|
||||||
|
filtered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (app.requirements != null) {
|
||||||
|
for (String r : app.requirements) {
|
||||||
|
if (r.equals("root") && !pref_rooted)
|
||||||
|
filtered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,9 @@
|
|||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Dictionary;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -52,7 +54,7 @@ public class DB {
|
|||||||
static void initDB(Context ctx) {
|
static void initDB(Context ctx) {
|
||||||
dbInstance = new DB(ctx);
|
dbInstance = new DB(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get access to the database. Must be called before any database activity,
|
// Get access to the database. Must be called before any database activity,
|
||||||
// and releaseDB must be called subsequently. Returns null in the event of
|
// and releaseDB must be called subsequently. Returns null in the event of
|
||||||
// failure.
|
// failure.
|
||||||
@ -90,7 +92,7 @@ public class DB {
|
|||||||
+ "installedVersion text," + "hasUpdates int not null,"
|
+ "installedVersion text," + "hasUpdates int not null,"
|
||||||
+ "primary key(id));";
|
+ "primary key(id));";
|
||||||
|
|
||||||
public static class App {
|
public static class App implements Comparable<App> {
|
||||||
|
|
||||||
public App() {
|
public App() {
|
||||||
name = "Unknown";
|
name = "Unknown";
|
||||||
@ -154,25 +156,22 @@ public class DB {
|
|||||||
// This should be the 'current' version, as in the most recent stable
|
// This should be the 'current' version, as in the most recent stable
|
||||||
// one, that most users would want by default. It might not be the
|
// one, that most users would want by default. It might not be the
|
||||||
// most recent, if for example there are betas etc.
|
// most recent, if for example there are betas etc.
|
||||||
// To skip compatibility checks, pass null as the checker.
|
public Apk getCurrentVersion() {
|
||||||
public Apk getCurrentVersion(DB.Apk.CompatibilityChecker checker) {
|
|
||||||
|
|
||||||
// Try and return the real current version first...
|
// Try and return the real current version first...
|
||||||
if (marketVersion != null && marketVercode > 0) {
|
if (marketVersion != null && marketVercode > 0) {
|
||||||
for (Apk apk : apks) {
|
for (Apk apk : apks) {
|
||||||
if (apk.vercode == marketVercode
|
if (apk.vercode == marketVercode)
|
||||||
&& (checker == null || checker.isCompatible(apk)))
|
|
||||||
return apk;
|
return apk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't know the current version, or we don't have it, we
|
// If we don't know the current version, or we don't have it, we
|
||||||
// return the most recent compatible version we have...
|
// return the most recent version we have...
|
||||||
int latestcode = -1;
|
int latestcode = -1;
|
||||||
Apk latestapk = null;
|
Apk latestapk = null;
|
||||||
for (Apk apk : apks) {
|
for (Apk apk : apks) {
|
||||||
if (apk.vercode > latestcode
|
if (apk.vercode > latestcode) {
|
||||||
&& (checker == null || checker.isCompatible(apk))) {
|
|
||||||
latestapk = apk;
|
latestapk = apk;
|
||||||
latestcode = apk.vercode;
|
latestcode = apk.vercode;
|
||||||
}
|
}
|
||||||
@ -180,6 +179,11 @@ public class DB {
|
|||||||
return latestapk;
|
return latestapk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(App arg0) {
|
||||||
|
return name.compareTo(arg0.name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The TABLE_APK table stores details of all the application versions we
|
// The TABLE_APK table stores details of all the application versions we
|
||||||
@ -298,12 +302,6 @@ public class DB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let other classes reuse the already instantiated compatibility
|
|
||||||
// checker, mostly to avoid redundant log output.
|
|
||||||
public Apk.CompatibilityChecker getCompatibilityChecker() {
|
|
||||||
return compatChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The TABLE_REPO table stores the details of the repositories in use.
|
// The TABLE_REPO table stores the details of the repositories in use.
|
||||||
private static final String TABLE_REPO = "fdroid_repo";
|
private static final String TABLE_REPO = "fdroid_repo";
|
||||||
private static final String CREATE_TABLE_REPO = "create table "
|
private static final String CREATE_TABLE_REPO = "create table "
|
||||||
@ -377,7 +375,10 @@ public class DB {
|
|||||||
// Version 14...
|
// Version 14...
|
||||||
{ "alter table " + TABLE_APK + " add added string",
|
{ "alter table " + TABLE_APK + " add added string",
|
||||||
"alter table " + TABLE_APP + " add added string",
|
"alter table " + TABLE_APP + " add added string",
|
||||||
"alter table " + TABLE_APP + " add lastUpdated string" } };
|
"alter table " + TABLE_APP + " add lastUpdated string" },
|
||||||
|
|
||||||
|
// Version 15...
|
||||||
|
{ "create index apk_vercode on " + TABLE_APK + " (vercode);" } };
|
||||||
|
|
||||||
private class DBHelper extends SQLiteOpenHelper {
|
private class DBHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
@ -416,7 +417,7 @@ public class DB {
|
|||||||
|
|
||||||
private PackageManager mPm;
|
private PackageManager mPm;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Apk.CompatibilityChecker compatChecker;
|
private Apk.CompatibilityChecker compatChecker = null;
|
||||||
|
|
||||||
// The date format used for storing dates (e.g. lastupdated, added) in the
|
// The date format used for storing dates (e.g. lastupdated, added) in the
|
||||||
// database.
|
// database.
|
||||||
@ -441,7 +442,6 @@ public class DB {
|
|||||||
sync_mode = null;
|
sync_mode = null;
|
||||||
if (sync_mode != null)
|
if (sync_mode != null)
|
||||||
Log.d("FDroid", "Database synchronization mode: " + sync_mode);
|
Log.d("FDroid", "Database synchronization mode: " + sync_mode);
|
||||||
compatChecker = Apk.CompatibilityChecker.getChecker(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
@ -462,9 +462,10 @@ public class DB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of apps that have updates available.
|
// Get the number of apps that have updates available. This can be a
|
||||||
|
// time consuming operation.
|
||||||
public int getNumUpdates() {
|
public int getNumUpdates() {
|
||||||
Vector<App> apps = getApps(null, null, false, true);
|
Vector<App> apps = getApps(true);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (App app : apps) {
|
for (App app : apps) {
|
||||||
if (app.hasUpdates)
|
if (app.hasUpdates)
|
||||||
@ -482,7 +483,6 @@ public class DB {
|
|||||||
c.moveToFirst();
|
c.moveToFirst();
|
||||||
while (!c.isAfterLast()) {
|
while (!c.isAfterLast()) {
|
||||||
String s = c.getString(c.getColumnIndex("category"));
|
String s = c.getString(c.getColumnIndex("category"));
|
||||||
Log.d("FDroid", "Category: " + s);
|
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
s = "none";
|
s = "none";
|
||||||
}
|
}
|
||||||
@ -504,157 +504,85 @@ public class DB {
|
|||||||
// Return a list of apps matching the given criteria. Filtering is
|
// Return a list of apps matching the given criteria. Filtering is
|
||||||
// also done based on compatibility and anti-features according to
|
// also done based on compatibility and anti-features according to
|
||||||
// the user's current preferences.
|
// the user's current preferences.
|
||||||
// 'appid' - specific app id to retrieve, or null
|
public Vector<App> getApps(boolean getinstalledinfo) {
|
||||||
// 'filter' - search text to filter on, or null
|
|
||||||
// 'update' - update installed version information from device, rather than
|
|
||||||
// simply using values cached in the database. Slower.
|
|
||||||
// 'exclusions' - apply filtering for compatibility, anti-features, etc.
|
|
||||||
public Vector<App> getApps(String appid, String filter, boolean update,
|
|
||||||
boolean exclusions) {
|
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager
|
Map<String, App> apps = new HashMap<String, App>();
|
||||||
.getDefaultSharedPreferences(mContext);
|
|
||||||
boolean pref_antiAds = prefs.getBoolean("antiAds", false);
|
|
||||||
boolean pref_antiTracking = prefs.getBoolean("antiTracking", false);
|
|
||||||
boolean pref_antiNonFreeAdd = prefs.getBoolean("antiNonFreeAdd", false);
|
|
||||||
boolean pref_antiNonFreeNet = prefs.getBoolean("antiNonFreeNet", false);
|
|
||||||
boolean pref_antiNonFreeDep = prefs.getBoolean("antiNonFreeDep", false);
|
|
||||||
boolean pref_showIncompat = prefs.getBoolean("showIncompatible", false);
|
|
||||||
boolean pref_rooted = prefs.getBoolean("rooted", true);
|
|
||||||
|
|
||||||
Vector<App> result = new Vector<App>();
|
|
||||||
Cursor c = null;
|
Cursor c = null;
|
||||||
Cursor c2 = null;
|
long startTime = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String query = "select * from " + TABLE_APP;
|
c = db.query(TABLE_APP, null, null, null, null, null, null);
|
||||||
if (appid != null) {
|
|
||||||
query += " where id = '" + appid + "'";
|
|
||||||
} else if (filter != null) {
|
|
||||||
query += " where name like '%" + filter + "%'"
|
|
||||||
+ " or description like '%" + filter + "%'";
|
|
||||||
}
|
|
||||||
query += " order by name collate nocase";
|
|
||||||
|
|
||||||
c = db.rawQuery(query, null);
|
|
||||||
c.moveToFirst();
|
c.moveToFirst();
|
||||||
while (!c.isAfterLast()) {
|
while (!c.isAfterLast()) {
|
||||||
|
|
||||||
App app = new App();
|
App app = new App();
|
||||||
app.antiFeatures = DB.CommaSeparatedList.make(c.getString(c
|
app.antiFeatures = DB.CommaSeparatedList.make(c.getString(c
|
||||||
.getColumnIndex("antiFeatures")));
|
.getColumnIndex("antiFeatures")));
|
||||||
boolean include = true;
|
|
||||||
if (app.antiFeatures != null && exclusions) {
|
|
||||||
for (String af : app.antiFeatures) {
|
|
||||||
if (af.equals("Ads") && !pref_antiAds)
|
|
||||||
include = false;
|
|
||||||
else if (af.equals("Tracking") && !pref_antiTracking)
|
|
||||||
include = false;
|
|
||||||
else if (af.equals("NonFreeNet")
|
|
||||||
&& !pref_antiNonFreeNet)
|
|
||||||
include = false;
|
|
||||||
else if (af.equals("NonFreeAdd")
|
|
||||||
&& !pref_antiNonFreeAdd)
|
|
||||||
include = false;
|
|
||||||
else if (af.equals("NonFreeDep")
|
|
||||||
&& !pref_antiNonFreeDep)
|
|
||||||
include = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
app.requirements = DB.CommaSeparatedList.make(c.getString(c
|
app.requirements = DB.CommaSeparatedList.make(c.getString(c
|
||||||
.getColumnIndex("requirements")));
|
.getColumnIndex("requirements")));
|
||||||
if (app.requirements != null && exclusions) {
|
app.id = c.getString(c.getColumnIndex("id"));
|
||||||
for (String r : app.requirements) {
|
app.name = c.getString(c.getColumnIndex("name"));
|
||||||
if (r.equals("root") && !pref_rooted) {
|
app.summary = c.getString(c.getColumnIndex("summary"));
|
||||||
include = false;
|
app.icon = c.getString(c.getColumnIndex("icon"));
|
||||||
}
|
app.description = c.getString(c.getColumnIndex("description"));
|
||||||
}
|
app.license = c.getString(c.getColumnIndex("license"));
|
||||||
}
|
app.category = c.getString(c.getColumnIndex("category"));
|
||||||
|
app.webURL = c.getString(c.getColumnIndex("webURL"));
|
||||||
|
app.trackerURL = c.getString(c.getColumnIndex("trackerURL"));
|
||||||
|
app.sourceURL = c.getString(c.getColumnIndex("sourceURL"));
|
||||||
|
app.donateURL = c.getString(c.getColumnIndex("donateURL"));
|
||||||
|
app.marketVersion = c.getString(c
|
||||||
|
.getColumnIndex("marketVersion"));
|
||||||
|
app.marketVercode = c.getInt(c.getColumnIndex("marketVercode"));
|
||||||
|
String sAdded = c.getString(c.getColumnIndex("added"));
|
||||||
|
app.added = (sAdded == null || sAdded.length() == 0) ? null
|
||||||
|
: mDateFormat.parse(sAdded);
|
||||||
|
String sLastUpdated = c.getString(c
|
||||||
|
.getColumnIndex("lastUpdated"));
|
||||||
|
app.lastUpdated = (sLastUpdated == null || sLastUpdated
|
||||||
|
.length() == 0) ? null : mDateFormat
|
||||||
|
.parse(sLastUpdated);
|
||||||
|
app.hasUpdates = false;
|
||||||
|
|
||||||
if (include) {
|
apps.put(app.id, app);
|
||||||
app.id = c.getString(c.getColumnIndex("id"));
|
|
||||||
app.name = c.getString(c.getColumnIndex("name"));
|
|
||||||
app.summary = c.getString(c.getColumnIndex("summary"));
|
|
||||||
app.icon = c.getString(c.getColumnIndex("icon"));
|
|
||||||
app.description = c.getString(c
|
|
||||||
.getColumnIndex("description"));
|
|
||||||
app.license = c.getString(c.getColumnIndex("license"));
|
|
||||||
app.category = c.getString(c.getColumnIndex("category"));
|
|
||||||
app.webURL = c.getString(c.getColumnIndex("webURL"));
|
|
||||||
app.trackerURL = c
|
|
||||||
.getString(c.getColumnIndex("trackerURL"));
|
|
||||||
app.sourceURL = c.getString(c.getColumnIndex("sourceURL"));
|
|
||||||
app.donateURL = c.getString(c.getColumnIndex("donateURL"));
|
|
||||||
app.installedVersion = c.getString(c
|
|
||||||
.getColumnIndex("installedVersion"));
|
|
||||||
app.installedVerCode = c.getInt(c
|
|
||||||
.getColumnIndex("installedVerCode"));
|
|
||||||
app.marketVersion = c.getString(c
|
|
||||||
.getColumnIndex("marketVersion"));
|
|
||||||
app.marketVercode = c.getInt(c
|
|
||||||
.getColumnIndex("marketVercode"));
|
|
||||||
String sAdded = c.getString(c.getColumnIndex("added"));
|
|
||||||
app.added = (sAdded == null || sAdded.length() == 0) ? null
|
|
||||||
: mDateFormat.parse(sAdded);
|
|
||||||
String sLastUpdated = c.getString(c
|
|
||||||
.getColumnIndex("lastUpdated"));
|
|
||||||
app.lastUpdated = (sLastUpdated == null || sLastUpdated
|
|
||||||
.length() == 0) ? null : mDateFormat
|
|
||||||
.parse(sLastUpdated);
|
|
||||||
app.hasUpdates = false;
|
|
||||||
|
|
||||||
c2 = db.rawQuery("select * from " + TABLE_APK
|
|
||||||
+ " where id = ? order by vercode desc",
|
|
||||||
new String[] { app.id });
|
|
||||||
c2.moveToFirst();
|
|
||||||
boolean compatible = pref_showIncompat || !exclusions;
|
|
||||||
while (!c2.isAfterLast()) {
|
|
||||||
Apk apk = new Apk();
|
|
||||||
apk.id = app.id;
|
|
||||||
apk.version = c2
|
|
||||||
.getString(c2.getColumnIndex("version"));
|
|
||||||
apk.vercode = c2.getInt(c2.getColumnIndex("vercode"));
|
|
||||||
apk.server = c2.getString(c2.getColumnIndex("server"));
|
|
||||||
apk.hash = c2.getString(c2.getColumnIndex("hash"));
|
|
||||||
apk.hashType = c2.getString(c2
|
|
||||||
.getColumnIndex("hashType"));
|
|
||||||
apk.sig = c2.getString(c2.getColumnIndex("sig"));
|
|
||||||
apk.srcname = c2
|
|
||||||
.getString(c2.getColumnIndex("srcname"));
|
|
||||||
apk.size = c2.getInt(c2.getColumnIndex("size"));
|
|
||||||
apk.apkName = c2
|
|
||||||
.getString(c2.getColumnIndex("apkName"));
|
|
||||||
apk.apkSource = c2.getString(c2
|
|
||||||
.getColumnIndex("apkSource"));
|
|
||||||
apk.minSdkVersion = c2.getInt(c2
|
|
||||||
.getColumnIndex("minSdkVersion"));
|
|
||||||
String sApkAdded = c2.getString(c2
|
|
||||||
.getColumnIndex("added"));
|
|
||||||
apk.added = (sApkAdded == null || sApkAdded.length() == 0) ? null
|
|
||||||
: mDateFormat.parse(sApkAdded);
|
|
||||||
apk.permissions = CommaSeparatedList.make(c2
|
|
||||||
.getString(c2.getColumnIndex("permissions")));
|
|
||||||
apk.features = CommaSeparatedList.make(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();
|
|
||||||
|
|
||||||
if (compatible) {
|
|
||||||
result.add(app);
|
|
||||||
} else {
|
|
||||||
Log.d("FDroid", "Excluding incompatible application: "
|
|
||||||
+ app.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.moveToNext();
|
c.moveToNext();
|
||||||
}
|
}
|
||||||
|
c.close();
|
||||||
|
c = null;
|
||||||
|
|
||||||
|
Log.d("FDroid", "Read app data from database " + " (took "
|
||||||
|
+ (System.currentTimeMillis() - startTime) + " ms)");
|
||||||
|
|
||||||
|
c = db.query(TABLE_APK, null, null, null, null, null,
|
||||||
|
"vercode desc");
|
||||||
|
c.moveToFirst();
|
||||||
|
while (!c.isAfterLast()) {
|
||||||
|
Apk apk = new Apk();
|
||||||
|
apk.id = c.getString(c.getColumnIndex("id"));
|
||||||
|
apk.version = c.getString(c.getColumnIndex("version"));
|
||||||
|
apk.vercode = c.getInt(c.getColumnIndex("vercode"));
|
||||||
|
apk.server = c.getString(c.getColumnIndex("server"));
|
||||||
|
apk.hash = c.getString(c.getColumnIndex("hash"));
|
||||||
|
apk.hashType = c.getString(c.getColumnIndex("hashType"));
|
||||||
|
apk.sig = c.getString(c.getColumnIndex("sig"));
|
||||||
|
apk.srcname = c.getString(c.getColumnIndex("srcname"));
|
||||||
|
apk.size = c.getInt(c.getColumnIndex("size"));
|
||||||
|
apk.apkName = c.getString(c.getColumnIndex("apkName"));
|
||||||
|
apk.apkSource = c.getString(c.getColumnIndex("apkSource"));
|
||||||
|
apk.minSdkVersion = c.getInt(c
|
||||||
|
.getColumnIndex("minSdkVersion"));
|
||||||
|
String sApkAdded = c.getString(c.getColumnIndex("added"));
|
||||||
|
apk.added = (sApkAdded == null || sApkAdded.length() == 0) ? null
|
||||||
|
: mDateFormat.parse(sApkAdded);
|
||||||
|
apk.permissions = CommaSeparatedList.make(c.getString(c
|
||||||
|
.getColumnIndex("permissions")));
|
||||||
|
apk.features = CommaSeparatedList.make(c.getString(c
|
||||||
|
.getColumnIndex("features")));
|
||||||
|
apps.get(apk.id).apks.add(apk);
|
||||||
|
c.moveToNext();
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("FDroid",
|
Log.e("FDroid",
|
||||||
@ -664,35 +592,28 @@ public class DB {
|
|||||||
if (c != null) {
|
if (c != null) {
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
if (c2 != null) {
|
|
||||||
c2.close();
|
Log.d("FDroid", "Read app and apk data from database " + " (took "
|
||||||
}
|
+ (System.currentTimeMillis() - startTime) + " ms)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update) {
|
Vector<App> result = new Vector<App>(apps.values());
|
||||||
db.beginTransaction();
|
Collections.sort(result);
|
||||||
try {
|
|
||||||
getUpdates(result);
|
|
||||||
db.setTransactionSuccessful();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("FDroid",
|
|
||||||
"Exception while getting updates: "
|
|
||||||
+ Log.getStackTraceString(e));
|
|
||||||
} finally {
|
|
||||||
db.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll say an application has updates if it's installed AND the
|
if (getinstalledinfo) {
|
||||||
// installed version is not the 'current' one AND the installed
|
getInstalledInfo(result);
|
||||||
// version is older than the current one.
|
|
||||||
for (App app : result) {
|
// We'll say an application has updates if it's installed AND the
|
||||||
Apk curver = app.getCurrentVersion(compatChecker);
|
// installed version is not the 'current' one AND the installed
|
||||||
if (curver != null && app.installedVersion != null
|
// version is older than the current one.
|
||||||
&& !app.installedVersion.equals(curver.version)) {
|
for (App app : result) {
|
||||||
if (app.installedVerCode < curver.vercode) {
|
Apk curver = app.getCurrentVersion();
|
||||||
app.hasUpdates = true;
|
if (curver != null && app.installedVersion != null
|
||||||
app.currentVersion = curver.version;
|
&& !app.installedVersion.equals(curver.version)) {
|
||||||
|
if (app.installedVerCode < curver.vercode) {
|
||||||
|
app.hasUpdates = true;
|
||||||
|
app.currentVersion = curver.version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,8 +621,8 @@ public class DB {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify installed status against the system's package list.
|
// Get installation status for all apps.
|
||||||
private void getUpdates(Vector<DB.App> apps) {
|
private void getInstalledInfo(Vector<DB.App> apps) {
|
||||||
List<PackageInfo> installedPackages = mPm.getInstalledPackages(0);
|
List<PackageInfo> installedPackages = mPm.getInstalledPackages(0);
|
||||||
Map<String, PackageInfo> systemApks = new HashMap<String, PackageInfo>();
|
Map<String, PackageInfo> systemApks = new HashMap<String, PackageInfo>();
|
||||||
Log.d("FDroid", "Reading installed packages");
|
Log.d("FDroid", "Reading installed packages");
|
||||||
@ -712,19 +633,11 @@ public class DB {
|
|||||||
for (DB.App app : apps) {
|
for (DB.App app : apps) {
|
||||||
if (systemApks.containsKey(app.id)) {
|
if (systemApks.containsKey(app.id)) {
|
||||||
PackageInfo sysapk = systemApks.get(app.id);
|
PackageInfo sysapk = systemApks.get(app.id);
|
||||||
String version = sysapk.versionName;
|
app.installedVersion = sysapk.versionName;
|
||||||
int vercode = sysapk.versionCode;
|
app.installedVerCode = sysapk.versionCode;
|
||||||
if (app.installedVersion == null
|
|
||||||
|| !app.installedVersion.equals(version)) {
|
|
||||||
setInstalledVersion(app.id, version, vercode);
|
|
||||||
app.installedVersion = version;
|
|
||||||
app.installedVerCode = vercode;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (app.installedVersion != null) {
|
app.installedVersion = null;
|
||||||
setInstalledVersion(app.id, null, 0);
|
app.installedVerCode = 0;
|
||||||
app.installedVersion = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,21 +673,27 @@ public class DB {
|
|||||||
|
|
||||||
private Vector<App> updateApps = null;
|
private Vector<App> updateApps = null;
|
||||||
|
|
||||||
// Called before a repo update starts.
|
// Called before a repo update starts. Returns the number of updates
|
||||||
public void beginUpdate() {
|
// available beforehand.
|
||||||
|
public int beginUpdate(Vector<DB.App> apps) {
|
||||||
// Get a list of all apps. All the apps and apks in this list will
|
// Get a list of all apps. All the apps and apks in this list will
|
||||||
// have 'updated' set to false at this point, and we will only set
|
// have 'updated' set to false at this point, and we will only set
|
||||||
// it to true when we see the app/apk in a repository. Thus, at the
|
// it to true when we see the app/apk in a repository. Thus, at the
|
||||||
// end, any that are still false can be removed.
|
// end, any that are still false can be removed.
|
||||||
// TODO: Need to ensure that UI and UpdateService can't both be doing
|
updateApps = apps;
|
||||||
// an update at the same time.
|
|
||||||
updateApps = getApps(null, null, true, false);
|
|
||||||
Log.d("FDroid", "AppUpdate: " + updateApps.size()
|
Log.d("FDroid", "AppUpdate: " + updateApps.size()
|
||||||
+ " apps before starting.");
|
+ " apps before starting.");
|
||||||
// Wrap the whole update in a transaction. Make sure to call
|
// Wrap the whole update in a transaction. Make sure to call
|
||||||
// either endUpdate or cancelUpdate to commit or discard it,
|
// either endUpdate or cancelUpdate to commit or discard it,
|
||||||
// respectively.
|
// respectively.
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (App app : updateApps) {
|
||||||
|
if (app.hasUpdates)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when a repo update ends. Any applications that have not been
|
// Called when a repo update ends. Any applications that have not been
|
||||||
@ -831,6 +750,21 @@ public class DB {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lazy initialise this...
|
||||||
|
if (compatChecker == null)
|
||||||
|
compatChecker = Apk.CompatibilityChecker.getChecker(mContext);
|
||||||
|
|
||||||
|
// See if it's compatible (by which we mean if it has at least one
|
||||||
|
// compatible apk - if it's not, leave it out)
|
||||||
|
// Also keep a list of which were compatible, because they're the
|
||||||
|
// only ones we'll add.
|
||||||
|
Vector<Apk> compatibleapks = new Vector<Apk>();
|
||||||
|
for (Apk apk : upapp.apks)
|
||||||
|
if (compatChecker.isCompatible(apk))
|
||||||
|
compatibleapks.add(apk);
|
||||||
|
if (compatibleapks.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (App app : updateApps) {
|
for (App app : updateApps) {
|
||||||
if (app.id.equals(upapp.id)) {
|
if (app.id.equals(upapp.id)) {
|
||||||
@ -839,7 +773,7 @@ public class DB {
|
|||||||
updateApp(app, upapp);
|
updateApp(app, upapp);
|
||||||
app.updated = true;
|
app.updated = true;
|
||||||
found = true;
|
found = true;
|
||||||
for (Apk upapk : upapp.apks) {
|
for (Apk upapk : compatibleapks) {
|
||||||
boolean afound = false;
|
boolean afound = false;
|
||||||
for (Apk apk : app.apks) {
|
for (Apk apk : app.apks) {
|
||||||
if (apk.version.equals(upapk.version)) {
|
if (apk.version.equals(upapk.version)) {
|
||||||
@ -869,7 +803,7 @@ public class DB {
|
|||||||
// .d("FDroid", "AppUpdate: " + upapp.id
|
// .d("FDroid", "AppUpdate: " + upapp.id
|
||||||
// + " is a new application.");
|
// + " is a new application.");
|
||||||
updateApp(null, upapp);
|
updateApp(null, upapp);
|
||||||
for (Apk upapk : upapp.apks) {
|
for (Apk upapk : compatibleapks) {
|
||||||
updateApkIfDifferent(null, upapk);
|
updateApkIfDifferent(null, upapk);
|
||||||
upapk.updated = true;
|
upapk.updated = true;
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,14 @@ import android.app.TabActivity;
|
|||||||
import android.app.AlertDialog.Builder;
|
import android.app.AlertDialog.Builder;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@ -144,7 +146,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
populateLists(true, true);
|
populateLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -322,11 +324,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate the lists.
|
// Populate the lists.
|
||||||
// 'update' - true to update the installed status of the applications
|
private void populateLists() {
|
||||||
// by asking the system.
|
|
||||||
// 'refreshdb' - true to refresh the list from the database rather
|
|
||||||
// than using the last one we got.
|
|
||||||
private void populateLists(boolean update, boolean refreshdb) {
|
|
||||||
|
|
||||||
apps_in.clear();
|
apps_in.clear();
|
||||||
apps_av.clear();
|
apps_av.clear();
|
||||||
@ -348,7 +346,6 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
cat_recentlyupdated = getString(R.string.category_recentlyupdated);
|
cat_recentlyupdated = getString(R.string.category_recentlyupdated);
|
||||||
categories.add(cat_all);
|
categories.add(cat_all);
|
||||||
for (String s : db.getCategories()) {
|
for (String s : db.getCategories()) {
|
||||||
Log.d("FDroid", "s: " + s);
|
|
||||||
categories.add(s);
|
categories.add(s);
|
||||||
}
|
}
|
||||||
categories.add(cat_whatsnew);
|
categories.add(cat_whatsnew);
|
||||||
@ -356,13 +353,12 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
if (currentCategory == null)
|
if (currentCategory == null)
|
||||||
currentCategory = cat_all;
|
currentCategory = cat_all;
|
||||||
|
|
||||||
if(apps == null || refreshdb || update)
|
|
||||||
apps = db.getApps(null, null, update, true);
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
DB.releaseDB();
|
DB.releaseDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apps = ((FDroidApp) getApplication()).getApps();
|
||||||
|
|
||||||
if (apps.isEmpty()) {
|
if (apps.isEmpty()) {
|
||||||
// Don't attempt this more than once - we may have invalid
|
// Don't attempt this more than once - we may have invalid
|
||||||
// repositories.
|
// repositories.
|
||||||
@ -382,6 +378,8 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
recent.add(Calendar.DAY_OF_YEAR, -14);
|
recent.add(Calendar.DAY_OF_YEAR, -14);
|
||||||
Date recentDate = recent.getTime();
|
Date recentDate = recent.getTime();
|
||||||
|
|
||||||
|
AppFilter appfilter = new AppFilter(this);
|
||||||
|
|
||||||
for (DB.App app : apps) {
|
for (DB.App app : apps) {
|
||||||
if (currentCategory.equals(cat_all)) {
|
if (currentCategory.equals(cat_all)) {
|
||||||
// Let everything through!
|
// Let everything through!
|
||||||
@ -403,15 +401,21 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
if (!currentCategory.equals(app.category))
|
if (!currentCategory.equals(app.category))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean filtered = appfilter.filter(app);
|
||||||
|
|
||||||
|
// Add it to the list(s). Always to installed and updates, but
|
||||||
|
// only to available if it's not filtered.
|
||||||
if (app.installedVersion == null) {
|
if (app.installedVersion == null) {
|
||||||
apps_av.addItem(app);
|
apps_av.addItem(app);
|
||||||
} else {
|
} else {
|
||||||
apps_in.addItem(app);
|
if (!filtered)
|
||||||
|
apps_in.addItem(app);
|
||||||
if (app.hasUpdates)
|
if (app.hasUpdates)
|
||||||
apps_up.addItem(app);
|
apps_up.addItem(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the count on the 'Updates' tab to show the number available.
|
// Update the count on the 'Updates' tab to show the number available.
|
||||||
// This is quite unpleasant, but seems to be the only way to do it.
|
// This is quite unpleasant, but seems to be the only way to do it.
|
||||||
TextView uptext = (TextView) tabHost.getTabWidget().getChildAt(2)
|
TextView uptext = (TextView) tabHost.getTabWidget().getChildAt(2)
|
||||||
@ -444,7 +448,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
Toast.makeText(FDroid.this, resultData.getString("errmsg"),
|
Toast.makeText(FDroid.this, resultData.getString("errmsg"),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
populateLists(true, true);
|
populateLists();
|
||||||
}
|
}
|
||||||
if (pd.isShowing())
|
if (pd.isShowing())
|
||||||
pd.dismiss();
|
pd.dismiss();
|
||||||
@ -470,7 +474,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
public void onItemSelected(AdapterView<?> parent, View view, int pos,
|
public void onItemSelected(AdapterView<?> parent, View view, int pos,
|
||||||
long id) {
|
long id) {
|
||||||
currentCategory = parent.getItemAtPosition(pos).toString();
|
currentCategory = parent.getItemAtPosition(pos).toString();
|
||||||
populateLists(false, false);
|
populateLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
|
||||||
public class FDroidApp extends Application {
|
public class FDroidApp extends Application {
|
||||||
@ -25,10 +28,60 @@ public class FDroidApp extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
|
apps = null;
|
||||||
DB.initDB(getApplicationContext());
|
DB.initDB(getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global list of all known applications.
|
||||||
|
private Vector<DB.App> apps;
|
||||||
|
|
||||||
|
// Set when something has changed (database or installed apps) so we know
|
||||||
|
// we should invalidate the apps.
|
||||||
|
private volatile boolean appsInvalid = false;
|
||||||
|
private Semaphore appsInvalidLock = new Semaphore(1, false);
|
||||||
|
|
||||||
|
// Set apps invalid. Call this when the database has been updated with
|
||||||
|
// new app information, or when the installed packages have changed.
|
||||||
|
public void invalidateApps() {
|
||||||
|
try {
|
||||||
|
appsInvalidLock.acquire();
|
||||||
|
appsInvalid = true;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Don't care
|
||||||
|
} finally {
|
||||||
|
appsInvalidLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of all known applications. Should not be called when the
|
||||||
|
// database is locked (i.e. between DB.getDB() and db.releaseDB(). The
|
||||||
|
// contents should never be modified, it's for reading only.
|
||||||
|
public Vector<DB.App> getApps() {
|
||||||
|
|
||||||
|
boolean invalid = false;
|
||||||
|
try {
|
||||||
|
appsInvalidLock.acquire();
|
||||||
|
invalid = appsInvalid;
|
||||||
|
if (invalid)
|
||||||
|
appsInvalid = false;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Don't care
|
||||||
|
} finally {
|
||||||
|
appsInvalidLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apps == null || invalid) {
|
||||||
|
try {
|
||||||
|
DB db = DB.getDB();
|
||||||
|
apps = db.getApps(true);
|
||||||
|
} finally {
|
||||||
|
DB.releaseDB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (apps == null)
|
||||||
|
return new Vector<DB.App>();
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,13 +67,18 @@ public class SearchResults extends ListActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateView() {
|
private void updateView() {
|
||||||
Vector<DB.App> apps;
|
|
||||||
try {
|
Vector<DB.App> apps= new Vector<DB.App>();
|
||||||
DB db = DB.getDB();
|
AppFilter appfilter = new AppFilter(this);
|
||||||
apps = db.getApps(null, mQuery, false, true);
|
String mq = mQuery.toLowerCase();
|
||||||
} finally {
|
Vector<DB.App> tapps = ((FDroidApp) getApplication()).getApps();
|
||||||
DB.releaseDB();
|
for(DB.App tapp : tapps) {
|
||||||
|
if(tapp.name.toLowerCase().contains(mq) || tapp.description.toLowerCase().contains(mq)) {
|
||||||
|
if(!appfilter.filter(tapp))
|
||||||
|
apps.add(tapp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView tv = (TextView) findViewById(R.id.description);
|
TextView tv = (TextView) findViewById(R.id.description);
|
||||||
String headertext;
|
String headertext;
|
||||||
if(apps.size()==0)
|
if(apps.size()==0)
|
||||||
|
@ -102,16 +102,7 @@ public class UpdateService extends IntentService {
|
|||||||
int newUpdates = 0;
|
int newUpdates = 0;
|
||||||
Vector<DB.Repo> repos;
|
Vector<DB.Repo> repos;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Get the number of updates available before we
|
|
||||||
// start, so we can notify if there are new ones.
|
|
||||||
// (But avoid doing it if the user doesn't want
|
|
||||||
// notifications, since it may be time consuming)
|
|
||||||
if (notify)
|
|
||||||
prevUpdates = db.getNumUpdates();
|
|
||||||
|
|
||||||
repos = db.getRepos();
|
repos = db.getRepos();
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
DB.releaseDB();
|
DB.releaseDB();
|
||||||
}
|
}
|
||||||
@ -136,13 +127,15 @@ public class UpdateService extends IntentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
Vector<DB.App> prevapps = ((FDroidApp)getApplication()).getApps();
|
||||||
db = DB.getDB();
|
db = DB.getDB();
|
||||||
try {
|
try {
|
||||||
db.beginUpdate();
|
prevUpdates = db.beginUpdate(prevapps);
|
||||||
for (DB.App app : apps) {
|
for (DB.App app : apps) {
|
||||||
db.updateApplication(app);
|
db.updateApplication(app);
|
||||||
}
|
}
|
||||||
db.endUpdate();
|
db.endUpdate();
|
||||||
|
((FDroidApp)getApplication()).invalidateApps();
|
||||||
if (notify)
|
if (notify)
|
||||||
newUpdates = db.getNumUpdates();
|
newUpdates = db.getNumUpdates();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user