diff --git a/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_normal.png b/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_normal.png
new file mode 100644
index 0000000000..b87ea6f965
Binary files /dev/null and b/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_normal.png differ
diff --git a/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_paused.png b/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_paused.png
new file mode 100644
index 0000000000..33780f9ba9
Binary files /dev/null and b/android/BOINC/res/drawable-hdpi/ic_stat_notify_boinc_paused.png differ
diff --git a/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_normal.png b/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_normal.png
new file mode 100644
index 0000000000..42dd3fcc9f
Binary files /dev/null and b/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_normal.png differ
diff --git a/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_paused.png b/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_paused.png
new file mode 100644
index 0000000000..b168b24e1e
Binary files /dev/null and b/android/BOINC/res/drawable-ldpi/ic_stat_notify_boinc_paused.png differ
diff --git a/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_normal.png b/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_normal.png
new file mode 100644
index 0000000000..9acfe941d5
Binary files /dev/null and b/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_normal.png differ
diff --git a/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_paused.png b/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_paused.png
new file mode 100644
index 0000000000..cf57611d96
Binary files /dev/null and b/android/BOINC/res/drawable-mdpi/ic_stat_notify_boinc_paused.png differ
diff --git a/android/BOINC/res/values/strings.xml b/android/BOINC/res/values/strings.xml
index eb21d708ec..4b605a7b7c 100644
--- a/android/BOINC/res/values/strings.xml
+++ b/android/BOINC/res/values/strings.xml
@@ -157,6 +157,9 @@
Autostart
BOINC starts on boot up
Start BOINC manually
+ Notification
+ Shown when client is working
+ Hidden
Used CPU cores (in %)
Pause when other CPU usage exceeds… (in %)
CPU limit (in %)
diff --git a/android/BOINC/src/edu/berkeley/boinc/AppPreferences.java b/android/BOINC/src/edu/berkeley/boinc/AppPreferences.java
index e8d48b5ad8..ce72bae2df 100644
--- a/android/BOINC/src/edu/berkeley/boinc/AppPreferences.java
+++ b/android/BOINC/src/edu/berkeley/boinc/AppPreferences.java
@@ -18,6 +18,7 @@
******************************************************************************/
package edu.berkeley.boinc;
+import edu.berkeley.boinc.client.ClientNotification;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
@@ -29,6 +30,7 @@ public class AppPreferences {
private SharedPreferences prefs;
private Boolean autostart;
+ private Boolean showNotification;
private Boolean showAdvanced;
public void readPrefs (Context ctx) {
@@ -37,6 +39,7 @@ public class AppPreferences {
}
//second parameter of reading function is the initial value after installation.
autostart = prefs.getBoolean("autostart", false);
+ showNotification = prefs.getBoolean("showNotification", true);
showAdvanced = prefs.getBoolean("showAdvanced", false);
Log.d(TAG, "appPrefs read successful." + autostart + showAdvanced);
@@ -52,6 +55,17 @@ public class AppPreferences {
public Boolean getAutostart () {
return this.autostart;
}
+
+ public void setShowNotification(Boolean as) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean("showNotification", as);
+ editor.commit();
+ this.showNotification = as;
+ }
+
+ public Boolean getShowNotification() {
+ return this.showNotification;
+ }
public void setShowAdvanced(Boolean as) {
SharedPreferences.Editor editor = prefs.edit();
diff --git a/android/BOINC/src/edu/berkeley/boinc/PrefsActivity.java b/android/BOINC/src/edu/berkeley/boinc/PrefsActivity.java
index a7db189cd1..770fc79479 100644
--- a/android/BOINC/src/edu/berkeley/boinc/PrefsActivity.java
+++ b/android/BOINC/src/edu/berkeley/boinc/PrefsActivity.java
@@ -24,6 +24,7 @@ import edu.berkeley.boinc.adapter.PrefsListAdapter;
import edu.berkeley.boinc.adapter.PrefsListItemWrapper;
import edu.berkeley.boinc.adapter.PrefsListItemWrapperBool;
import edu.berkeley.boinc.adapter.PrefsListItemWrapperDouble;
+import edu.berkeley.boinc.client.ClientNotification;
import edu.berkeley.boinc.client.Monitor;
import edu.berkeley.boinc.rpc.GlobalPreferences;
import android.app.AlertDialog;
@@ -130,7 +131,8 @@ public class PrefsActivity extends FragmentActivity {
Boolean advanced = appPrefs.getShowAdvanced();
data.add(new PrefsListItemWrapper(this,R.string.prefs_category_general,true));
- data.add(new PrefsListItemWrapperBool(this,R.string.prefs_autostart_header,R.string.prefs_category_general,appPrefs.getAutostart()));
+ data.add(new PrefsListItemWrapperBool(this,R.string.prefs_autostart_header,R.string.prefs_category_general,appPrefs.getAutostart()));
+ data.add(new PrefsListItemWrapperBool(this,R.string.prefs_show_notification_header,R.string.prefs_category_general,appPrefs.getShowNotification()));
data.add(new PrefsListItemWrapperBool(this,R.string.prefs_show_advanced_header,R.string.prefs_category_general,appPrefs.getShowAdvanced()));
data.add(new PrefsListItemWrapper(this,R.string.prefs_category_network,true));
data.add(new PrefsListItemWrapperBool(this,R.string.prefs_network_wifi_only_header,R.string.prefs_category_network,clientPrefs.network_wifi_only));
@@ -167,6 +169,12 @@ public class PrefsActivity extends FragmentActivity {
appPrefs.setAutostart(isSet);
populateLayout();
break;
+ case R.string.prefs_show_notification_header: //app pref
+ appPrefs.setShowNotification(isSet);
+ //TODO: needs to be checked against app design. Is does not look to be at the right place
+ // Enable/disable notification instantly
+ ClientNotification.getInstance().enable(getApplicationContext(), isSet);
+ break;
case R.string.prefs_show_advanced_header: //app pref
appPrefs.setShowAdvanced(isSet);
// call reload of list directly, whithout detour via setDataOutdated and waiting for event.
diff --git a/android/BOINC/src/edu/berkeley/boinc/adapter/PrefsListItemWrapperBool.java b/android/BOINC/src/edu/berkeley/boinc/adapter/PrefsListItemWrapperBool.java
index 3a294ce0d3..4d2dab497d 100644
--- a/android/BOINC/src/edu/berkeley/boinc/adapter/PrefsListItemWrapperBool.java
+++ b/android/BOINC/src/edu/berkeley/boinc/adapter/PrefsListItemWrapperBool.java
@@ -46,6 +46,11 @@ public class PrefsListItemWrapperBool extends PrefsListItemWrapper {
status_true = ctx.getString(R.string.prefs_autostart_true);
status_false = ctx.getString(R.string.prefs_autostart_false);
break;
+ case R.string.prefs_show_notification_header:
+ header = ctx.getString(R.string.prefs_show_notification_header);
+ status_true = ctx.getString(R.string.prefs_show_notification_true);
+ status_false = ctx.getString(R.string.prefs_show_notification_false);
+ break;
case R.string.prefs_run_on_battery_header:
header = ctx.getString(R.string.prefs_run_on_battery_header);
status_true = ctx.getString(R.string.prefs_run_on_battery_true);
diff --git a/android/BOINC/src/edu/berkeley/boinc/client/ClientNotification.java b/android/BOINC/src/edu/berkeley/boinc/client/ClientNotification.java
new file mode 100644
index 0000000000..11972fbfe0
--- /dev/null
+++ b/android/BOINC/src/edu/berkeley/boinc/client/ClientNotification.java
@@ -0,0 +1,105 @@
+package edu.berkeley.boinc.client;
+
+import edu.berkeley.boinc.BOINCActivity;
+import edu.berkeley.boinc.R;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+public class ClientNotification {
+ private static final String TAG = "ClientNotification";
+
+ private static final int NOTIFICATION_ID = 460;
+
+ private static ClientNotification clientNotification = null;
+
+ private boolean mIsEnabled = true;
+ private int mOldComputingStatus = -1;
+
+ private ClientNotification() {
+
+ }
+
+ /**
+ * Returns a reference to a singleton ClientNotification object.
+ * Constructs a new instance of the ClientNotification if not already constructed.
+ * @return ClientNotification static instance
+ */
+ public static synchronized ClientNotification getInstance() {
+ if (clientNotification == null)
+ clientNotification = new ClientNotification();
+
+ return clientNotification;
+ }
+
+ /**
+ * Updates notification with client's current status
+ * @param context
+ * @param updatedStatus new status
+ */
+ public synchronized void update(Context context, ClientStatus updatedStatus) {
+ if (clientNotification.mOldComputingStatus == -1
+ || updatedStatus.computingStatus.intValue() != clientNotification.mOldComputingStatus) {
+ if (clientNotification.mIsEnabled)
+ updateNotification(context, updatedStatus.computingStatus);
+ clientNotification.mOldComputingStatus = updatedStatus.computingStatus;
+ }
+ }
+
+ /**
+ * Set notification enabled/disabled
+ * @param context
+ * @param enabled
+ */
+ public synchronized void enable(Context context, boolean enabled) {
+ clientNotification.mIsEnabled = enabled;
+ if (clientNotification.mIsEnabled) {
+ if (clientNotification.mOldComputingStatus != -1)
+ updateNotification(context, clientNotification.mOldComputingStatus);
+ } else {
+ hide(context);
+ }
+ }
+
+ private void updateNotification(Context context, int status) {
+ switch(status) {
+ case ClientStatus.COMPUTING_STATUS_NEVER:
+// hide(context);
+// break;
+ case ClientStatus.COMPUTING_STATUS_SUSPENDED:
+ case ClientStatus.COMPUTING_STATUS_IDLE:
+ show(context, R.drawable.ic_stat_notify_boinc_paused, R.string.status_idle, BOINCActivity.class);
+ break;
+ case ClientStatus.COMPUTING_STATUS_COMPUTING:
+ show(context, R.drawable.ic_stat_notify_boinc_normal, R.string.status_running, BOINCActivity.class);
+ break;
+ }
+ }
+
+ private void show(Context context, int icon, int message, Class> launchActivity) {
+
+ // Set the icon, scrolling text and time-stamp
+ Notification notification = new Notification(
+ icon,
+ context.getText(message),
+ System.currentTimeMillis());
+ // The PendingIntent to launch activity
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
+ new Intent(context, launchActivity), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(context, context.getText(R.string.app_name),
+ context.getText(message), pendingIntent);
+ notification.flags |= Notification.FLAG_NO_CLEAR;
+
+ NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify(NOTIFICATION_ID, notification);
+ }
+
+ private void hide(Context context) {
+ NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.cancel(NOTIFICATION_ID);
+ }
+}
diff --git a/android/BOINC/src/edu/berkeley/boinc/client/Monitor.java b/android/BOINC/src/edu/berkeley/boinc/client/Monitor.java
index cb83dd7fbe..6726f35f8e 100644
--- a/android/BOINC/src/edu/berkeley/boinc/client/Monitor.java
+++ b/android/BOINC/src/edu/berkeley/boinc/client/Monitor.java
@@ -922,6 +922,8 @@ public class Monitor extends Service {
if( (status != null) && (results != null) && (projects != null) && (transfers != null)) {
Monitor.getClientStatus().setClientStatus(status, results, projects, transfers);
+ // Update status bar notification
+ ClientNotification.getInstance().update(getApplicationContext(), getClientStatus());
} else {
Log.d(TAG, "client status connection problem");
}