From 50a9d50fdece21b8538b6534cb973dcc5cad336a Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sun, 31 Oct 2010 14:13:52 +0000 Subject: Factor out the start/stopForeground and notification icon management into a separate class, don't let RockboxService.java become a beast. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28416 a1c6a512-1295-4272-9138-f99709370657 --- android/android.make | 4 +- .../org/rockbox/Helper/RunForegroundManager.java | 157 +++++++++++++++++++++ android/src/org/rockbox/RockboxActivity.java | 1 + android/src/org/rockbox/RockboxKeyboardInput.java | 1 + android/src/org/rockbox/RockboxService.java | 142 ++----------------- 5 files changed, 176 insertions(+), 129 deletions(-) create mode 100644 android/src/org/rockbox/Helper/RunForegroundManager.java (limited to 'android') diff --git a/android/android.make b/android/android.make index 492c0127cb..9ca760e470 100644 --- a/android/android.make +++ b/android/android.make @@ -37,9 +37,11 @@ MANIFEST := $(ANDROID_DIR)/AndroidManifest.xml R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class -JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java) +JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java) +JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java) JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC))) + LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk TEMP_APK2 := $(BUILDDIR)/bin/__rockbox.apk diff --git a/android/src/org/rockbox/Helper/RunForegroundManager.java b/android/src/org/rockbox/Helper/RunForegroundManager.java new file mode 100644 index 0000000000..eb6e4c96ef --- /dev/null +++ b/android/src/org/rockbox/Helper/RunForegroundManager.java @@ -0,0 +1,157 @@ +package org.rockbox.Helper; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.rockbox.R; +import org.rockbox.RockboxActivity; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.util.Log; + +public class RunForegroundManager +{ + /* all below is heavily based on the examples found on + * http://developer.android.com/reference/android/app/Service.html#setForeground(boolean) + */ + private Notification mNotification; + private NotificationManager mNM; + private IRunForeground api; + private Service mCurrentService; + + public RunForegroundManager(Service service) throws Exception + { + mNM = (NotificationManager) + service.getSystemService(Service.NOTIFICATION_SERVICE); + /* For now we'll use the same text for the ticker and the + * expanded notification */ + CharSequence text = service.getText(R.string.notification); + /* Set the icon, scrolling text and timestamp */ + mNotification = new Notification(R.drawable.icon, text, + System.currentTimeMillis()); + + /* The PendingIntent to launch our activity if the user selects + * this notification */ + Intent intent = new Intent(service, RockboxActivity.class); + PendingIntent contentIntent = + PendingIntent.getActivity(service, 0, intent, 0); + + /* Set the info for the views that show in the notification panel. */ + mNotification.setLatestEventInfo(service, + service.getText(R.string.notification), text, contentIntent); + + try { + api = new newForegroundApi(R.string.notification, mNotification); + } catch (NoSuchMethodException e) { + /* Fall back on the old API */ + api = new oldForegroundApi(); + } + mCurrentService = service; + } + + private void LOG(CharSequence text, Throwable tr) + { + Log.d("Rockbox", (String)text, tr); + } + + public void startForeground() + { + /* + * Send the notification. + * We use a layout id because it is a unique number. + * We use it later to cancel. + */ + mNM.notify(R.string.notification, mNotification); + /* + * this call makes the service run as foreground, which + * provides enough cpu time to do music decoding in the + * background + */ + api.startForeground(); + } + + public void stopForeground() + { + /* Note to cancel BEFORE changing the + * foreground state, since we could be killed at that point. + */ + mNM.cancel(R.string.notification); + api.stopForeground(); + } + + + private interface IRunForeground + { + void startForeground(); + void stopForeground(); + } + + private class newForegroundApi implements IRunForeground + { + Class[] mStartForegroundSignature = + new Class[] { int.class, Notification.class }; + Class[] mStopForegroundSignature = + new Class[] { boolean.class }; + private Method mStartForeground; + private Method mStopForeground; + private Object[] mStartForegroundArgs = new Object[2]; + private Object[] mStopForegroundArgs = new Object[1]; + + newForegroundApi(int id, Notification notification) + throws SecurityException, NoSuchMethodException + { + /* + * Get the new API through reflection + */ + mStartForeground = Service.class.getMethod("startForeground", + mStartForegroundSignature); + mStopForeground = Service.class.getMethod("stopForeground", + mStopForegroundSignature); + mStartForegroundArgs[0] = id; + mStartForegroundArgs[1] = notification; + mStopForegroundArgs[0] = Boolean.TRUE; + } + + public void startForeground() + { + try { + mStartForeground.invoke(mCurrentService, mStartForegroundArgs); + } catch (InvocationTargetException e) { + /* Should not happen. */ + LOG("Unable to invoke startForeground", e); + } catch (IllegalAccessException e) { + /* Should not happen. */ + LOG("Unable to invoke startForeground", e); + } + } + + public void stopForeground() + { + try { + mStopForeground.invoke(mCurrentService, mStopForegroundArgs); + } catch (InvocationTargetException e) { + /* Should not happen. */ + LOG("Unable to invoke stopForeground", e); + } catch (IllegalAccessException e) { + /* Should not happen. */ + LOG("Unable to invoke stopForeground", e); + } + } + } + + private class oldForegroundApi implements IRunForeground + { + public void startForeground() + { + mCurrentService.setForeground(false); + } + public void stopForeground() + { + mCurrentService.setForeground(false); + } + } +} diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java index fed17c67f9..d8c1307ff3 100644 --- a/android/src/org/rockbox/RockboxActivity.java +++ b/android/src/org/rockbox/RockboxActivity.java @@ -21,6 +21,7 @@ package org.rockbox; + import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; diff --git a/android/src/org/rockbox/RockboxKeyboardInput.java b/android/src/org/rockbox/RockboxKeyboardInput.java index 5601b16662..3024b6b685 100644 --- a/android/src/org/rockbox/RockboxKeyboardInput.java +++ b/android/src/org/rockbox/RockboxKeyboardInput.java @@ -21,6 +21,7 @@ package org.rockbox; + import android.app.Activity; import android.content.Intent; diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java index 63ebd27566..b841bc5d7f 100644 --- a/android/src/org/rockbox/RockboxService.java +++ b/android/src/org/rockbox/RockboxService.java @@ -21,14 +21,14 @@ package org.rockbox; +import org.rockbox.Helper.RunForegroundManager; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Enumeration; import java.util.Timer; import java.util.TimerTask; @@ -36,9 +36,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import android.app.Activity; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; @@ -62,21 +59,10 @@ public class RockboxService extends Service /* locals needed for the c code and rockbox state */ private RockboxFramebuffer fb = null; private boolean mRockboxRunning = false; - private Activity current_activity = null; - - private Notification notification; - private static final Class[] mStartForegroundSignature = - new Class[] { int.class, Notification.class }; - private static final Class[] mStopForegroundSignature = - new Class[] { boolean.class }; - - private NotificationManager mNM; - private Method mStartForeground; - private Method mStopForeground; - private Object[] mStartForegroundArgs = new Object[2]; - private Object[] mStopForegroundArgs = new Object[1]; + private Activity current_activity = null; private IntentFilter itf; private BroadcastReceiver batt_monitor; + private RunForegroundManager fg_runner; @SuppressWarnings("unused") private int battery_level; @@ -84,19 +70,6 @@ public class RockboxService extends Service public void onCreate() { instance = this; - mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - try - { - mStartForeground = getClass().getMethod("startForeground", - mStartForegroundSignature); - mStopForeground = getClass().getMethod("stopForeground", - mStopForegroundSignature); - } - catch (NoSuchMethodException e) - { - /* Running on an older platform: fall back to old API */ - mStartForeground = mStopForeground = null; - } startservice(); } @@ -132,7 +105,11 @@ public class RockboxService extends Service /* Display a notification about us starting. * We put an icon in the status bar. */ - create_notification(); + try { + fg_runner = new RunForegroundManager(this); + } catch (Exception e) { + e.printStackTrace(); + } } private void LOG(CharSequence text) @@ -285,105 +262,14 @@ public class RockboxService extends Service registerReceiver(batt_monitor, itf); } - /* all below is heavily based on the examples found on - * http://developer.android.com/reference/android/app/Service.html - */ - - private void create_notification() + public void startForeground() { - /* For now we'll use the same text for the ticker and the - * expanded notification */ - CharSequence text = getText(R.string.notification); - /* Set the icon, scrolling text and timestamp */ - notification = new Notification(R.drawable.icon, text, - System.currentTimeMillis()); - - /* The PendingIntent to launch our activity if the user selects - * this notification */ - Intent intent = new Intent(this, RockboxActivity.class); - PendingIntent contentIntent = - PendingIntent.getActivity(this, 0, intent, 0); - - /* Set the info for the views that show in the notification panel. */ - notification.setLatestEventInfo(this, - getText(R.string.notification), text, contentIntent); - } - - public void startForeground() - { - /* - * Send the notification. - * We use a layout id because it is a unique number. - * We use it later to cancel. - */ - mNM.notify(R.string.notification, instance.notification); - /* - * this call makes the service run as foreground, which - * provides enough cpu time to do music decoding in the - * background - */ - startForegroundCompat(R.string.notification, notification); + fg_runner.startForeground(); } - public void stopForeground() - { - if (notification != null) - { - stopForegroundCompat(R.string.notification); - mNM.cancel(R.string.notification); - } - } - - /** - * This is a wrapper around the new startForeground method, using the older - * APIs if it is not available. - */ - void startForegroundCompat(int id, Notification notification) + public void stopForeground() { - if (mStartForeground != null) { - mStartForegroundArgs[0] = Integer.valueOf(id); - mStartForegroundArgs[1] = notification; - try { - mStartForeground.invoke(this, mStartForegroundArgs); - } catch (InvocationTargetException e) { - /* Should not happen. */ - LOG("Unable to invoke startForeground", e); - } catch (IllegalAccessException e) { - /* Should not happen. */ - LOG("Unable to invoke startForeground", e); - } - return; - } - - /* Fall back on the old API.*/ - setForeground(true); - mNM.notify(id, notification); - } - - /** - * This is a wrapper around the new stopForeground method, using the older - * APIs if it is not available. - */ - void stopForegroundCompat(int id) - { - if (mStopForeground != null) { - mStopForegroundArgs[0] = Boolean.TRUE; - try { - mStopForeground.invoke(this, mStopForegroundArgs); - } catch (InvocationTargetException e) { - /* Should not happen. */ - LOG("Unable to invoke stopForeground", e); - } catch (IllegalAccessException e) { - /* Should not happen. */ - LOG("Unable to invoke stopForeground", e); - } - return; - } - - /* Fall back on the old API. Note to cancel BEFORE changing the - * foreground state, since we could be killed at that point. */ - mNM.cancel(id); - setForeground(false); + fg_runner.stopForeground(); } @Override @@ -391,6 +277,6 @@ public class RockboxService extends Service { super.onDestroy(); /* Make sure our notification is gone. */ - stopForegroundCompat(R.string.notification); + stopForeground(); } } -- cgit v1.2.3