diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java index f4c6821b1..8d99d1c29 100644 --- a/src/org/fdroid/fdroid/AppDetails.java +++ b/src/org/fdroid/fdroid/AppDetails.java @@ -200,7 +200,6 @@ public class AppDetails extends ListActivity { db = new DB(this); compatChecker = db.getCompatibilityChecker(); mPm = getPackageManager(); - ((FDroidApp) getApplication()).inActivity++; // Get the preferences we're going to use in this Activity... SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(getBaseContext()); @@ -238,7 +237,6 @@ public class AppDetails extends ListActivity { protected void onStop() { db.close(); db = null; - ((FDroidApp) getApplication()).inActivity--; super.onStop(); } diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java index 59a5dbeb3..6d5562656 100644 --- a/src/org/fdroid/fdroid/FDroid.java +++ b/src/org/fdroid/fdroid/FDroid.java @@ -31,6 +31,7 @@ import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.TabActivity; import android.app.AlertDialog.Builder; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; @@ -39,6 +40,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.ResultReceiver; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -135,7 +137,6 @@ public class FDroid extends TabActivity implements OnItemClickListener, @Override protected void onStart() { super.onStart(); - ((FDroidApp) getApplication()).inActivity++; db = new DB(this); triedEmptyUpdate = false; populateLists(true); @@ -144,7 +145,6 @@ public class FDroid extends TabActivity implements OnItemClickListener, @Override protected void onStop() { db.close(); - ((FDroidApp) getApplication()).inActivity--; super.onStop(); } @@ -415,26 +415,15 @@ public class FDroid extends TabActivity implements OnItemClickListener, } - private void updateRepos() { - pd = ProgressDialog.show(this, getString(R.string.process_wait_title), - getString(R.string.process_update_msg), true); - pd.setIcon(android.R.drawable.ic_dialog_info); - - new Thread() { - public void run() { - boolean success = RepoXMLHandler.doUpdates(FDroid.this, db); - update_handler.sendEmptyMessage(success ? 0 : 1); - } - }.start(); - } - - /* - * Handlers for thread functions that need to access GUI - */ - private Handler update_handler = new Handler() { + // For receiving results from the UpdateService when we've told it to + // update in response to a user request. + private class UpdateReceiver extends ResultReceiver { + public UpdateReceiver(Handler handler) { + super(handler); + } @Override - public void handleMessage(Message msg) { - if (msg.what == 1) { + protected void onReceiveResult (int resultCode, Bundle resultData) { + if (resultCode == 1) { Toast.makeText(FDroid.this, getString(R.string.connection_error_msg), Toast.LENGTH_LONG).show(); @@ -444,7 +433,22 @@ public class FDroid extends TabActivity implements OnItemClickListener, if (pd.isShowing()) pd.dismiss(); } - }; + } + private UpdateReceiver mUpdateReceiver; + + // Force a repo update now. A progress dialog is shown and the UpdateService + // is told to do the update, which will result in the database changing. The + // UpdateReceiver class should get told when this is finished. + private void updateRepos() { + pd = ProgressDialog.show(this, getString(R.string.process_wait_title), + getString(R.string.process_update_msg), true, true); + pd.setIcon(android.R.drawable.ic_dialog_info); + + Intent intent = new Intent(this, UpdateService.class); + mUpdateReceiver = new UpdateReceiver(new Handler()); + intent.putExtra("receiver", mUpdateReceiver); + startService(intent); + } public void onItemSelected(AdapterView parent, View view, int pos, long id) { diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java index 3670466dc..aab5031c2 100644 --- a/src/org/fdroid/fdroid/FDroidApp.java +++ b/src/org/fdroid/fdroid/FDroidApp.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Ciaran Gultnieks, ciaran@ciarang.com + * 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 @@ -22,10 +22,5 @@ import android.app.Application; public class FDroidApp extends Application { - // Keeps track of when we are in one of our activities where we - // don't want a database update to run. Incremented when entering - // one, and decremented when leaving, so if it's 0 it ought to be - // ok! - public int inActivity = 0; } diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index f2b43e663..a87106849 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Ciaran Gultnieks, ciaran@ciarang.com + * 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 @@ -19,6 +19,7 @@ package org.fdroid.fdroid; import android.app.AlarmManager; +import android.app.IntentService; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -26,12 +27,19 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.os.Bundle; import android.os.IBinder; +import android.os.ResultReceiver; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.Log; -public class UpdateService extends Service { +public class UpdateService extends IntentService { + + public UpdateService() { + super("UpdateService"); + } + // Schedule (or cancel schedule for) this service, according to the // current preferences. Should be called a) at boot, or b) if the preference @@ -55,103 +63,89 @@ public class UpdateService extends Service { SystemClock.elapsedRealtime() + 5000, AlarmManager.INTERVAL_HOUR, pending); } - } - // For API levels <5 - @Override - public void onStart(Intent intent, int startId) { - handleCommand(); - } - // For API levels >=5 - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - handleCommand(); - return START_REDELIVER_INTENT; - } + protected void onHandleIntent(Intent intent) { - private void handleCommand() { + // We might be doing a scheduled run, or we might have been launched by + // the app in response to a user's request. If we get this receiver, it's + // the latter... + ResultReceiver receiver = intent.getParcelableExtra("receiver"); + + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(getBaseContext()); - new Thread() { - public void run() { + // See if it's time to actually do anything yet... + if(receiver == null) { + long lastUpdate = prefs.getLong("lastUpdateCheck", 0); + String sint = prefs.getString("updateInterval", "0"); + int interval = Integer.parseInt(sint); + if (interval == 0) + return; + if (lastUpdate + (interval * 60 * 60) > System + .currentTimeMillis()) + return; + } - // If we're in one of our list activities, we don't want - // to run an update because the database will be out of - // sync with the display. - if (((FDroidApp) getApplication()).inActivity != 0) - return; + // Do the update... + DB db = null; + try { + db = new DB(getBaseContext()); + boolean notify = prefs.getBoolean("updateNotify", false); - // See if it's time to actually do anything yet... - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(getBaseContext()); - long lastUpdate = prefs.getLong("lastUpdateCheck", 0); - String sint = prefs.getString("updateInterval", "0"); - int interval = Integer.parseInt(sint); - if (interval == 0) - return; - if (lastUpdate + (interval * 60 * 60) > System - .currentTimeMillis()) - return; + // 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) + int prevUpdates = 0; + if (notify) + prevUpdates = db.getNumUpdates(); - // Do the update... - DB db = null; - try { - db = new DB(getBaseContext()); - boolean notify = prefs.getBoolean("updateNotify", false); + boolean success = RepoXMLHandler.doUpdates( + getBaseContext(), db); - // 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) - int prevUpdates = 0; - if (notify) - prevUpdates = db.getNumUpdates(); - - boolean success = RepoXMLHandler.doUpdates( - getBaseContext(), db); - - if (success && notify) { - int newUpdates = db.getNumUpdates(); - Log.d("FDroid", "Updates before:" + prevUpdates + ", after: " +newUpdates); - if (newUpdates > prevUpdates) { - NotificationManager n = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - Notification notification = new Notification( - R.drawable.icon, - "FDroid Updates Available", System - .currentTimeMillis()); - Context context = getApplicationContext(); - CharSequence contentTitle = "FDroid"; - CharSequence contentText = "Updates are available."; - Intent notificationIntent = new Intent( - UpdateService.this, FDroid.class); - PendingIntent contentIntent = PendingIntent - .getActivity(UpdateService.this, 0, - notificationIntent, 0); - notification.setLatestEventInfo(context, - contentTitle, contentText, contentIntent); - notification.flags |= Notification.FLAG_AUTO_CANCEL; - n.notify(1, notification); - } - } - - } catch (Exception e) { - Log.e("FDroid", "Exception during handleCommand():\n" - + Log.getStackTraceString(e)); - } finally { - if (db != null) - db.close(); - stopSelf(); + if (success && notify) { + int newUpdates = db.getNumUpdates(); + Log.d("FDroid", "Updates before:" + prevUpdates + ", after: " +newUpdates); + if (newUpdates > prevUpdates) { + NotificationManager n = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new Notification( + R.drawable.icon, + "FDroid Updates Available", System + .currentTimeMillis()); + Context context = getApplicationContext(); + CharSequence contentTitle = "FDroid"; + CharSequence contentText = "Updates are available."; + Intent notificationIntent = new Intent( + UpdateService.this, FDroid.class); + PendingIntent contentIntent = PendingIntent + .getActivity(UpdateService.this, 0, + notificationIntent, 0); + notification.setLatestEventInfo(context, + contentTitle, contentText, contentIntent); + notification.flags |= Notification.FLAG_AUTO_CANCEL; + n.notify(1, notification); } - } - }.start(); + + if(receiver != null) { + Bundle resultData = new Bundle(); + receiver.send(0, resultData); + } - } + } catch (Exception e) { + Log.e("FDroid", "Exception during handleCommand():\n" + + Log.getStackTraceString(e)); + if(receiver != null) { + Bundle resultData = new Bundle(); + receiver.send(1, resultData); + } + } finally { + if (db != null) + db.close(); + } - @Override - public IBinder onBind(Intent intent) { - return null; } }