diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-03 22:56:24 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-03 22:56:24 +0000 |
commit | 9dd0158ffb98ddbd5bef0e45a9b561294ce50264 (patch) | |
tree | 7df364f01c95c6f9b9b0a831aa802670eb4a0933 | |
parent | 83c60a1012f2db6c21c5779f7e11b2f3e479df85 (diff) |
Run Rockbox as a service, which allows for music decoding&playback in the background,
the activity only attaches to the framebuffer for displaying it. An icon
in the notification area is displayed (it could be prettier I guess).
Note: Some HTC phones won't, includng mine, get enough CPU time to do background decoding
fluently, see: http://code.google.com/p/android/issues/detail?id=9663
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27686 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | android/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | android/default.properties | 2 | ||||
-rw-r--r-- | android/gen/org/rockbox/R.java | 2 | ||||
-rw-r--r-- | android/res/values/strings.xml | 1 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxActivity.java | 159 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxTimer.java | 17 | ||||
-rw-r--r-- | firmware/target/hosted/android/kernel-android.c | 2 | ||||
-rw-r--r-- | firmware/target/hosted/android/lcd-android.c | 12 | ||||
-rw-r--r-- | firmware/target/hosted/android/pcm-android.c | 2 | ||||
-rw-r--r-- | firmware/target/hosted/android/system-android.c | 10 |
10 files changed, 74 insertions, 136 deletions
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index a22c393379..30acaf09f7 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -10,7 +10,8 @@ <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> - </activity> + </activity> + <service android:name=".RockboxService"/> </application> <uses-sdk android:minSdkVersion="4" /> diff --git a/android/default.properties b/android/default.properties index 9d79b12c71..9d135cb85f 100644 --- a/android/default.properties +++ b/android/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-4 +target=android-7 diff --git a/android/gen/org/rockbox/R.java b/android/gen/org/rockbox/R.java index 38c177ef36..50f3456e5f 100644 --- a/android/gen/org/rockbox/R.java +++ b/android/gen/org/rockbox/R.java @@ -12,11 +12,13 @@ public final class R { } public static final class drawable { public static final int icon=0x7f020000; + public static final int rb=0x7f020001; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040000; + public static final int notification=0x7f040001; } } diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 6c3c8464fd..9320b2624d 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -2,4 +2,5 @@ <resources> <string name="app_name">Rockbox</string> +<string name="notification">Rockbox</string> </resources> diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java index 791cad90ff..eadfd5a40a 100644 --- a/android/src/org/rockbox/RockboxActivity.java +++ b/android/src/org/rockbox/RockboxActivity.java @@ -21,128 +21,81 @@ package org.rockbox; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - import android.app.Activity; -import android.graphics.Rect; +import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; public class RockboxActivity extends Activity { /** Called when the activity is first created. */ - public RockboxFramebuffer fb; - private Thread rb; - static final int BUFFER = 2048; - /** Called when the activity is first created. */ @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) + { super.onCreate(savedInstanceState); - LOG("start rb"); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN - ,WindowManager.LayoutParams.FLAG_FULLSCREEN); - fb = new RockboxFramebuffer(this); - if (true) { - try + ,WindowManager.LayoutParams.FLAG_FULLSCREEN); + final Intent intent = new Intent(this, + RockboxService.class); + startService(intent); + /* Now it gets a bit tricky: + * The service is started in the same thread as we are now, + * but the service also initializes the framebuffer + * Unforunately, this happens *after* any of the default + * startup methods of an activity, so we need to poll for it + * + * In order to get the fb, we need to let the Service start up + * run, we can wait in a separate thread for fb to get ready + * This thread waits for the fb to become ready */ + new Thread(new Runnable() { - BufferedOutputStream dest = null; - BufferedInputStream is = null; - ZipEntry entry; - File file = new File("/data/data/org.rockbox/lib/libmisc.so"); - /* use arbitary file to determine whether extracting is needed */ - File file2 = new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec"); - if (!file2.exists() || (file.lastModified() > file2.lastModified())) - { - ZipFile zipfile = new ZipFile(file); - Enumeration<? extends ZipEntry> e = zipfile.entries(); - File folder; - while(e.hasMoreElements()) { - entry = (ZipEntry) e.nextElement(); - LOG("Extracting: " +entry); - if (entry.isDirectory()) - { - folder = new File(entry.getName()); - LOG("mkdir "+ entry); - try { - folder.mkdirs(); - } catch (SecurityException ex){ - LOG(ex.getMessage()); - } - continue; - } - is = new BufferedInputStream(zipfile.getInputStream(entry)); - int count; - byte data[] = new byte[BUFFER]; - folder = new File(new File(entry.getName()).getParent()); - LOG("" + folder.getAbsolutePath()); - if (!folder.exists()) - folder.mkdirs(); - FileOutputStream fos = new FileOutputStream(entry.getName()); - dest = new BufferedOutputStream(fos, BUFFER); - while ((count = is.read(data, 0, BUFFER)) != -1) { - dest.write(data, 0, count); - } - dest.flush(); - dest.close(); - is.close(); - } - } - } catch(Exception e) { - e.printStackTrace(); - }} - Rect r = new Rect(); - fb.getDrawingRect(r); - LOG(r.left + " " + r.top + " " + r.right + " " + r.bottom); - rb = new Thread(new Runnable() - { - public void run() - { - main(); - } - },"Rockbox thread"); - System.loadLibrary("rockbox"); - rb.setDaemon(false); - setContentView(fb); - } - - private void LOG(CharSequence text) - { - Log.d("RockboxBootloader", (String) text); - } - - public synchronized void onStart() - { - super.onStart(); - if (!rb.isAlive()) - rb.start(); - } - - public void onPause() - { - super.onPause(); + public void run() { + while (RockboxService.fb == null) + { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } catch (Exception e) { + LOG(e.toString()); + } + /* drawing needs to happen in ui thread */ + runOnUiThread(new Runnable() + { @Override + public void run() { + setContentView(RockboxService.fb); + RockboxService.fb.invalidate(); + } + }); + } + + } + }).start(); } public void onResume() { super.onResume(); - switch (rb.getState()) { - case BLOCKED: LOG("BLOCKED"); break; - case RUNNABLE: LOG("RUNNABLE"); break; - case NEW: LOG("NEW"); break; - case TERMINATED: LOG("TERMINATED"); break; - case TIMED_WAITING: LOG("TIMED_WAITING"); break; - case WAITING: LOG("WAITING"); break; + if (RockboxService.fb != null) + { + try { + setContentView(RockboxService.fb); + } catch (IllegalStateException e) { + /* we are already using the View, + * need to remove it and re-attach it */ + ViewGroup g = (ViewGroup)RockboxService.fb.getParent(); + g.removeView(RockboxService.fb); + setContentView(RockboxService.fb); + } catch (Exception e) { + LOG(e.toString()); + } } } - - private native void main(); + private void LOG(CharSequence text) + { + Log.d("Rockbox", (String) text); + } }
\ No newline at end of file diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java index c7239b4ee6..6491e4ffe9 100644 --- a/android/src/org/rockbox/RockboxTimer.java +++ b/android/src/org/rockbox/RockboxTimer.java @@ -47,21 +47,6 @@ public class RockboxTimer extends Timer } } - public void pause() - { - cancel(); - } - public void resume() - { - try { - schedule(task, 0, interval); - } catch (IllegalStateException e) { - /* not an error */ - } catch (Exception e) { - LOG(e.toString()); - } - } - public RockboxTimer(long period_inverval_in_ms) { super("tick timer", false); @@ -72,7 +57,7 @@ public class RockboxTimer extends Timer private void LOG(CharSequence text) { - Log.d("RockboxBootloader", (String) text); + Log.d("Rockbox", (String) text); } diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c index 9594516460..1a9b97b419 100644 --- a/firmware/target/hosted/android/kernel-android.c +++ b/firmware/target/hosted/android/kernel-android.c @@ -25,8 +25,6 @@ #include "system.h" extern JNIEnv *env_ptr; -extern jclass RockboxActivity_class; -extern jobject RockboxActivity_instance; static jclass RockboxTimer_class; static jobject RockboxTimer_instance; diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c index ef4004ef2a..efe68cdd71 100644 --- a/firmware/target/hosted/android/lcd-android.c +++ b/firmware/target/hosted/android/lcd-android.c @@ -26,8 +26,8 @@ #include "lcd.h" extern JNIEnv *env_ptr; -extern jclass RockboxActivity_class; -extern jobject RockboxActivity_instance; +extern jclass RockboxService_class; +extern jobject RockboxService_instance; static jobject Framebuffer_instance; static jmethodID java_lcd_update; @@ -35,13 +35,13 @@ static jmethodID java_lcd_update; void lcd_init_device(void) { /* get the RockboxFramebuffer instance allocated by the activity */ - jfieldID id = (*env_ptr)->GetFieldID(env_ptr, - RockboxActivity_class, + jfieldID id = (*env_ptr)->GetStaticFieldID(env_ptr, + RockboxService_class, "fb", "Lorg/rockbox/RockboxFramebuffer;"); - Framebuffer_instance = (*env_ptr)->GetObjectField(env_ptr, - RockboxActivity_instance, + Framebuffer_instance = (*env_ptr)->GetStaticObjectField(env_ptr, + RockboxService_class, id); jclass Framebuffer_class = (*env_ptr)->GetObjectClass(env_ptr, diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c index 91978f422b..8c5d2597c4 100644 --- a/firmware/target/hosted/android/pcm-android.c +++ b/firmware/target/hosted/android/pcm-android.c @@ -25,8 +25,6 @@ #include "pcm.h" extern JNIEnv *env_ptr; -extern jclass RockboxActivity_class; -extern jobject RockboxActivity_instance; /* infos about our pcm chunks */ static size_t pcm_data_size; diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c index 16c6973474..1fb69b3465 100644 --- a/firmware/target/hosted/android/system-android.c +++ b/firmware/target/hosted/android/system-android.c @@ -32,8 +32,8 @@ void system_init(void) { } /* global fields for use with various JNI calls */ JNIEnv *env_ptr; -jobject RockboxActivity_instance; -jclass RockboxActivity_class; +jobject RockboxService_instance; +jclass RockboxService_class; uintptr_t *stackbegin; uintptr_t *stackend; @@ -41,7 +41,7 @@ uintptr_t *stackend; extern int main(void); /* this is the entry point of the android app initially called by jni */ JNIEXPORT void JNICALL -Java_org_rockbox_RockboxActivity_main(JNIEnv *env, jobject this) +Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) { /* hack!!! we can't have a valid stack pointer otherwise. * but we don't really need it anyway, thread.c only needs it @@ -53,7 +53,7 @@ Java_org_rockbox_RockboxActivity_main(JNIEnv *env, jobject this) volatile uintptr_t stack = 0; stackbegin = stackend = (uintptr_t*) &stack; env_ptr = env; - RockboxActivity_instance = this; - RockboxActivity_class = (*env)->GetObjectClass(env, this); + RockboxService_instance = this; + RockboxService_class = (*env)->GetObjectClass(env, this); main(); } |