summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/android.make4
-rw-r--r--android/src/org/rockbox/Helper/RunForegroundManager.java157
-rw-r--r--android/src/org/rockbox/RockboxActivity.java1
-rw-r--r--android/src/org/rockbox/RockboxKeyboardInput.java1
-rw-r--r--android/src/org/rockbox/RockboxService.java142
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
37R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java 37R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java
38R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class 38R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class
39 39
40JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java) 40JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java)
41JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java)
41JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC))) 42JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC)))
42 43
44
43LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so 45LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so
44TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk 46TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk
45TEMP_APK2 := $(BUILDDIR)/bin/__rockbox.apk 47TEMP_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 @@
1package org.rockbox.Helper;
2
3import java.lang.reflect.InvocationTargetException;
4import java.lang.reflect.Method;
5
6import org.rockbox.R;
7import org.rockbox.RockboxActivity;
8
9import android.app.Notification;
10import android.app.NotificationManager;
11import android.app.PendingIntent;
12import android.app.Service;
13import android.content.Intent;
14import android.util.Log;
15
16public 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
22package org.rockbox; 22package org.rockbox;
23 23
24
24import android.app.Activity; 25import android.app.Activity;
25import android.app.ProgressDialog; 26import android.app.ProgressDialog;
26import android.content.Intent; 27import 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
22package org.rockbox; 22package org.rockbox;
23 23
24
24import android.app.Activity; 25import android.app.Activity;
25import android.content.Intent; 26import 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
22package org.rockbox; 22package org.rockbox;
23 23
24import org.rockbox.Helper.RunForegroundManager;
25
24import java.io.BufferedInputStream; 26import java.io.BufferedInputStream;
25import java.io.BufferedOutputStream; 27import java.io.BufferedOutputStream;
26import java.io.File; 28import java.io.File;
27import java.io.FileNotFoundException; 29import java.io.FileNotFoundException;
28import java.io.FileOutputStream; 30import java.io.FileOutputStream;
29import java.io.IOException; 31import java.io.IOException;
30import java.lang.reflect.InvocationTargetException;
31import java.lang.reflect.Method;
32import java.util.Enumeration; 32import java.util.Enumeration;
33import java.util.Timer; 33import java.util.Timer;
34import java.util.TimerTask; 34import java.util.TimerTask;
@@ -36,9 +36,6 @@ import java.util.zip.ZipEntry;
36import java.util.zip.ZipFile; 36import java.util.zip.ZipFile;
37 37
38import android.app.Activity; 38import android.app.Activity;
39import android.app.Notification;
40import android.app.NotificationManager;
41import android.app.PendingIntent;
42import android.app.Service; 39import android.app.Service;
43import android.content.BroadcastReceiver; 40import android.content.BroadcastReceiver;
44import android.content.Context; 41import 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}