diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-10-31 14:13:52 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-10-31 14:13:52 +0000 |
commit | 50a9d50fdece21b8538b6534cb973dcc5cad336a (patch) | |
tree | f9a4ff2a19d70182acb2c4e7ef57a352d2c2d151 | |
parent | b92eabd38b6c06d598e85dcfc6e2244631efa11f (diff) | |
download | rockbox-50a9d50fdece21b8538b6534cb973dcc5cad336a.tar.gz rockbox-50a9d50fdece21b8538b6534cb973dcc5cad336a.zip |
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
-rw-r--r-- | android/android.make | 4 | ||||
-rw-r--r-- | android/src/org/rockbox/Helper/RunForegroundManager.java | 157 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxActivity.java | 1 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxKeyboardInput.java | 1 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxService.java | 142 |
5 files changed, 176 insertions, 129 deletions
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 | |||
37 | R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java | 37 | R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java |
38 | R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class | 38 | R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class |
39 | 39 | ||
40 | JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java) | 40 | JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java) |
41 | JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java) | ||
41 | JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC))) | 42 | JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC))) |
42 | 43 | ||
44 | |||
43 | LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so | 45 | LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so |
44 | TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk | 46 | TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk |
45 | TEMP_APK2 := $(BUILDDIR)/bin/__rockbox.apk | 47 | 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 @@ | |||
1 | package org.rockbox.Helper; | ||
2 | |||
3 | import java.lang.reflect.InvocationTargetException; | ||
4 | import java.lang.reflect.Method; | ||
5 | |||
6 | import org.rockbox.R; | ||
7 | import org.rockbox.RockboxActivity; | ||
8 | |||
9 | import android.app.Notification; | ||
10 | import android.app.NotificationManager; | ||
11 | import android.app.PendingIntent; | ||
12 | import android.app.Service; | ||
13 | import android.content.Intent; | ||
14 | import android.util.Log; | ||
15 | |||
16 | public class RunForegroundManager | ||
17 | { | ||
18 | /* all below is heavily based on the examples found on | ||
19 | * http://developer.android.com/reference/android/app/Service.html#setForeground(boolean) | ||
20 | */ | ||
21 | private Notification mNotification; | ||
22 | private NotificationManager mNM; | ||
23 | private IRunForeground api; | ||
24 | private Service mCurrentService; | ||
25 | |||
26 | public RunForegroundManager(Service service) throws Exception | ||
27 | { | ||
28 | mNM = (NotificationManager) | ||
29 | service.getSystemService(Service.NOTIFICATION_SERVICE); | ||
30 | /* For now we'll use the same text for the ticker and the | ||
31 | * expanded notification */ | ||
32 | CharSequence text = service.getText(R.string.notification); | ||
33 | /* Set the icon, scrolling text and timestamp */ | ||
34 | mNotification = new Notification(R.drawable.icon, text, | ||
35 | System.currentTimeMillis()); | ||
36 | |||
37 | /* The PendingIntent to launch our activity if the user selects | ||
38 | * this notification */ | ||
39 | Intent intent = new Intent(service, RockboxActivity.class); | ||
40 | PendingIntent contentIntent = | ||
41 | PendingIntent.getActivity(service, 0, intent, 0); | ||
42 | |||
43 | /* Set the info for the views that show in the notification panel. */ | ||
44 | mNotification.setLatestEventInfo(service, | ||
45 | service.getText(R.string.notification), text, contentIntent); | ||
46 | |||
47 | try { | ||
48 | api = new newForegroundApi(R.string.notification, mNotification); | ||
49 | } catch (NoSuchMethodException e) { | ||
50 | /* Fall back on the old API */ | ||
51 | api = new oldForegroundApi(); | ||
52 | } | ||
53 | mCurrentService = service; | ||
54 | } | ||
55 | |||
56 | private void LOG(CharSequence text, Throwable tr) | ||
57 | { | ||
58 | Log.d("Rockbox", (String)text, tr); | ||
59 | } | ||
60 | |||
61 | public void startForeground() | ||
62 | { | ||
63 | /* | ||
64 | * Send the notification. | ||
65 | * We use a layout id because it is a unique number. | ||
66 | * We use it later to cancel. | ||
67 | */ | ||
68 | mNM.notify(R.string.notification, mNotification); | ||
69 | /* | ||
70 | * this call makes the service run as foreground, which | ||
71 | * provides enough cpu time to do music decoding in the | ||
72 | * background | ||
73 | */ | ||
74 | api.startForeground(); | ||
75 | } | ||
76 | |||
77 | public void stopForeground() | ||
78 | { | ||
79 | /* Note to cancel BEFORE changing the | ||
80 | * foreground state, since we could be killed at that point. | ||
81 | */ | ||
82 | mNM.cancel(R.string.notification); | ||
83 | api.stopForeground(); | ||
84 | } | ||
85 | |||
86 | |||
87 | private interface IRunForeground | ||
88 | { | ||
89 | void startForeground(); | ||
90 | void stopForeground(); | ||
91 | } | ||
92 | |||
93 | private class newForegroundApi implements IRunForeground | ||
94 | { | ||
95 | Class<?>[] mStartForegroundSignature = | ||
96 | new Class[] { int.class, Notification.class }; | ||
97 | Class<?>[] mStopForegroundSignature = | ||
98 | new Class[] { boolean.class }; | ||
99 | private Method mStartForeground; | ||
100 | private Method mStopForeground; | ||
101 | private Object[] mStartForegroundArgs = new Object[2]; | ||
102 | private Object[] mStopForegroundArgs = new Object[1]; | ||
103 | |||
104 | newForegroundApi(int id, Notification notification) | ||
105 | throws SecurityException, NoSuchMethodException | ||
106 | { | ||
107 | /* | ||
108 | * Get the new API through reflection | ||
109 | */ | ||
110 | mStartForeground = Service.class.getMethod("startForeground", | ||
111 | mStartForegroundSignature); | ||
112 | mStopForeground = Service.class.getMethod("stopForeground", | ||
113 | mStopForegroundSignature); | ||
114 | mStartForegroundArgs[0] = id; | ||
115 | mStartForegroundArgs[1] = notification; | ||
116 | mStopForegroundArgs[0] = Boolean.TRUE; | ||
117 | } | ||
118 | |||
119 | public void startForeground() | ||
120 | { | ||
121 | try { | ||
122 | mStartForeground.invoke(mCurrentService, mStartForegroundArgs); | ||
123 | } catch (InvocationTargetException e) { | ||
124 | /* Should not happen. */ | ||
125 | LOG("Unable to invoke startForeground", e); | ||
126 | } catch (IllegalAccessException e) { | ||
127 | /* Should not happen. */ | ||
128 | LOG("Unable to invoke startForeground", e); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | public void stopForeground() | ||
133 | { | ||
134 | try { | ||
135 | mStopForeground.invoke(mCurrentService, mStopForegroundArgs); | ||
136 | } catch (InvocationTargetException e) { | ||
137 | /* Should not happen. */ | ||
138 | LOG("Unable to invoke stopForeground", e); | ||
139 | } catch (IllegalAccessException e) { | ||
140 | /* Should not happen. */ | ||
141 | LOG("Unable to invoke stopForeground", e); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | private class oldForegroundApi implements IRunForeground | ||
147 | { | ||
148 | public void startForeground() | ||
149 | { | ||
150 | mCurrentService.setForeground(false); | ||
151 | } | ||
152 | public void stopForeground() | ||
153 | { | ||
154 | mCurrentService.setForeground(false); | ||
155 | } | ||
156 | } | ||
157 | } | ||
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 @@ | |||
21 | 21 | ||
22 | package org.rockbox; | 22 | package org.rockbox; |
23 | 23 | ||
24 | |||
24 | import android.app.Activity; | 25 | import android.app.Activity; |
25 | import android.app.ProgressDialog; | 26 | import android.app.ProgressDialog; |
26 | import android.content.Intent; | 27 | 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 @@ | |||
21 | 21 | ||
22 | package org.rockbox; | 22 | package org.rockbox; |
23 | 23 | ||
24 | |||
24 | import android.app.Activity; | 25 | import android.app.Activity; |
25 | import android.content.Intent; | 26 | import android.content.Intent; |
26 | 27 | ||
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 @@ | |||
21 | 21 | ||
22 | package org.rockbox; | 22 | package org.rockbox; |
23 | 23 | ||
24 | import org.rockbox.Helper.RunForegroundManager; | ||
25 | |||
24 | import java.io.BufferedInputStream; | 26 | import java.io.BufferedInputStream; |
25 | import java.io.BufferedOutputStream; | 27 | import java.io.BufferedOutputStream; |
26 | import java.io.File; | 28 | import java.io.File; |
27 | import java.io.FileNotFoundException; | 29 | import java.io.FileNotFoundException; |
28 | import java.io.FileOutputStream; | 30 | import java.io.FileOutputStream; |
29 | import java.io.IOException; | 31 | import java.io.IOException; |
30 | import java.lang.reflect.InvocationTargetException; | ||
31 | import java.lang.reflect.Method; | ||
32 | import java.util.Enumeration; | 32 | import java.util.Enumeration; |
33 | import java.util.Timer; | 33 | import java.util.Timer; |
34 | import java.util.TimerTask; | 34 | import java.util.TimerTask; |
@@ -36,9 +36,6 @@ import java.util.zip.ZipEntry; | |||
36 | import java.util.zip.ZipFile; | 36 | import java.util.zip.ZipFile; |
37 | 37 | ||
38 | import android.app.Activity; | 38 | import android.app.Activity; |
39 | import android.app.Notification; | ||
40 | import android.app.NotificationManager; | ||
41 | import android.app.PendingIntent; | ||
42 | import android.app.Service; | 39 | import android.app.Service; |
43 | import android.content.BroadcastReceiver; | 40 | import android.content.BroadcastReceiver; |
44 | import android.content.Context; | 41 | import android.content.Context; |
@@ -62,21 +59,10 @@ public class RockboxService extends Service | |||
62 | /* locals needed for the c code and rockbox state */ | 59 | /* locals needed for the c code and rockbox state */ |
63 | private RockboxFramebuffer fb = null; | 60 | private RockboxFramebuffer fb = null; |
64 | private boolean mRockboxRunning = false; | 61 | private boolean mRockboxRunning = false; |
65 | private Activity current_activity = null; | 62 | private Activity current_activity = null; |
66 | |||
67 | private Notification notification; | ||
68 | private static final Class<?>[] mStartForegroundSignature = | ||
69 | new Class[] { int.class, Notification.class }; | ||
70 | private static final Class<?>[] mStopForegroundSignature = | ||
71 | new Class[] { boolean.class }; | ||
72 | |||
73 | private NotificationManager mNM; | ||
74 | private Method mStartForeground; | ||
75 | private Method mStopForeground; | ||
76 | private Object[] mStartForegroundArgs = new Object[2]; | ||
77 | private Object[] mStopForegroundArgs = new Object[1]; | ||
78 | private IntentFilter itf; | 63 | private IntentFilter itf; |
79 | private BroadcastReceiver batt_monitor; | 64 | private BroadcastReceiver batt_monitor; |
65 | private RunForegroundManager fg_runner; | ||
80 | @SuppressWarnings("unused") | 66 | @SuppressWarnings("unused") |
81 | private int battery_level; | 67 | private int battery_level; |
82 | 68 | ||
@@ -84,19 +70,6 @@ public class RockboxService extends Service | |||
84 | public void onCreate() | 70 | public void onCreate() |
85 | { | 71 | { |
86 | instance = this; | 72 | instance = this; |
87 | mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); | ||
88 | try | ||
89 | { | ||
90 | mStartForeground = getClass().getMethod("startForeground", | ||
91 | mStartForegroundSignature); | ||
92 | mStopForeground = getClass().getMethod("stopForeground", | ||
93 | mStopForegroundSignature); | ||
94 | } | ||
95 | catch (NoSuchMethodException e) | ||
96 | { | ||
97 | /* Running on an older platform: fall back to old API */ | ||
98 | mStartForeground = mStopForeground = null; | ||
99 | } | ||
100 | startservice(); | 73 | startservice(); |
101 | } | 74 | } |
102 | 75 | ||
@@ -132,7 +105,11 @@ public class RockboxService extends Service | |||
132 | 105 | ||
133 | /* Display a notification about us starting. | 106 | /* Display a notification about us starting. |
134 | * We put an icon in the status bar. */ | 107 | * We put an icon in the status bar. */ |
135 | create_notification(); | 108 | try { |
109 | fg_runner = new RunForegroundManager(this); | ||
110 | } catch (Exception e) { | ||
111 | e.printStackTrace(); | ||
112 | } | ||
136 | } | 113 | } |
137 | 114 | ||
138 | private void LOG(CharSequence text) | 115 | private void LOG(CharSequence text) |
@@ -285,105 +262,14 @@ public class RockboxService extends Service | |||
285 | registerReceiver(batt_monitor, itf); | 262 | registerReceiver(batt_monitor, itf); |
286 | } | 263 | } |
287 | 264 | ||
288 | /* all below is heavily based on the examples found on | 265 | public void startForeground() |
289 | * http://developer.android.com/reference/android/app/Service.html | ||
290 | */ | ||
291 | |||
292 | private void create_notification() | ||
293 | { | 266 | { |
294 | /* For now we'll use the same text for the ticker and the | 267 | fg_runner.startForeground(); |
295 | * expanded notification */ | ||
296 | CharSequence text = getText(R.string.notification); | ||
297 | /* Set the icon, scrolling text and timestamp */ | ||
298 | notification = new Notification(R.drawable.icon, text, | ||
299 | System.currentTimeMillis()); | ||
300 | |||
301 | /* The PendingIntent to launch our activity if the user selects | ||
302 | * this notification */ | ||
303 | Intent intent = new Intent(this, RockboxActivity.class); | ||
304 | PendingIntent contentIntent = | ||
305 | PendingIntent.getActivity(this, 0, intent, 0); | ||
306 | |||
307 | /* Set the info for the views that show in the notification panel. */ | ||
308 | notification.setLatestEventInfo(this, | ||
309 | getText(R.string.notification), text, contentIntent); | ||
310 | } | ||
311 | |||
312 | public void startForeground() | ||
313 | { | ||
314 | /* | ||
315 | * Send the notification. | ||
316 | * We use a layout id because it is a unique number. | ||
317 | * We use it later to cancel. | ||
318 | */ | ||
319 | mNM.notify(R.string.notification, instance.notification); | ||
320 | /* | ||
321 | * this call makes the service run as foreground, which | ||
322 | * provides enough cpu time to do music decoding in the | ||
323 | * background | ||
324 | */ | ||
325 | startForegroundCompat(R.string.notification, notification); | ||
326 | } | 268 | } |
327 | 269 | ||
328 | public void stopForeground() | 270 | public void stopForeground() |
329 | { | ||
330 | if (notification != null) | ||
331 | { | ||
332 | stopForegroundCompat(R.string.notification); | ||
333 | mNM.cancel(R.string.notification); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * This is a wrapper around the new startForeground method, using the older | ||
339 | * APIs if it is not available. | ||
340 | */ | ||
341 | void startForegroundCompat(int id, Notification notification) | ||
342 | { | 271 | { |
343 | if (mStartForeground != null) { | 272 | fg_runner.stopForeground(); |
344 | mStartForegroundArgs[0] = Integer.valueOf(id); | ||
345 | mStartForegroundArgs[1] = notification; | ||
346 | try { | ||
347 | mStartForeground.invoke(this, mStartForegroundArgs); | ||
348 | } catch (InvocationTargetException e) { | ||
349 | /* Should not happen. */ | ||
350 | LOG("Unable to invoke startForeground", e); | ||
351 | } catch (IllegalAccessException e) { | ||
352 | /* Should not happen. */ | ||
353 | LOG("Unable to invoke startForeground", e); | ||
354 | } | ||
355 | return; | ||
356 | } | ||
357 | |||
358 | /* Fall back on the old API.*/ | ||
359 | setForeground(true); | ||
360 | mNM.notify(id, notification); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * This is a wrapper around the new stopForeground method, using the older | ||
365 | * APIs if it is not available. | ||
366 | */ | ||
367 | void stopForegroundCompat(int id) | ||
368 | { | ||
369 | if (mStopForeground != null) { | ||
370 | mStopForegroundArgs[0] = Boolean.TRUE; | ||
371 | try { | ||
372 | mStopForeground.invoke(this, mStopForegroundArgs); | ||
373 | } catch (InvocationTargetException e) { | ||
374 | /* Should not happen. */ | ||
375 | LOG("Unable to invoke stopForeground", e); | ||
376 | } catch (IllegalAccessException e) { | ||
377 | /* Should not happen. */ | ||
378 | LOG("Unable to invoke stopForeground", e); | ||
379 | } | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | /* Fall back on the old API. Note to cancel BEFORE changing the | ||
384 | * foreground state, since we could be killed at that point. */ | ||
385 | mNM.cancel(id); | ||
386 | setForeground(false); | ||
387 | } | 273 | } |
388 | 274 | ||
389 | @Override | 275 | @Override |
@@ -391,6 +277,6 @@ public class RockboxService extends Service | |||
391 | { | 277 | { |
392 | super.onDestroy(); | 278 | super.onDestroy(); |
393 | /* Make sure our notification is gone. */ | 279 | /* Make sure our notification is gone. */ |
394 | stopForegroundCompat(R.string.notification); | 280 | stopForeground(); |
395 | } | 281 | } |
396 | } | 282 | } |