From eaff333bf526225cfca84cd686fe5332b852e506 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Sun, 31 Oct 2010 10:35:55 +0000 Subject: [PATCH] Use a Native keyboard GUI instead of rockbox's internal one on android git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28407 a1c6a512-1295-4272-9138-f99709370657 --- android/AndroidManifest.xml | 3 +- android/res/layout/keyboardinput.xml | 4 + android/res/values/strings.xml | 3 + android/src/org/rockbox/HostCallback.java | 7 ++ android/src/org/rockbox/KeyboardActivity.java | 41 +++++++++ android/src/org/rockbox/RockboxActivity.java | 33 ++++++- .../src/org/rockbox/RockboxFramebuffer.java | 3 +- .../src/org/rockbox/RockboxKeyboardInput.java | 69 +++++++++++++++ android/src/org/rockbox/RockboxService.java | 12 +++ apps/SOURCES | 4 + apps/hosted/keyboard.c | 86 +++++++++++++++++++ 11 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 android/res/layout/keyboardinput.xml create mode 100644 android/src/org/rockbox/HostCallback.java create mode 100644 android/src/org/rockbox/KeyboardActivity.java create mode 100644 android/src/org/rockbox/RockboxKeyboardInput.java create mode 100644 apps/hosted/keyboard.c diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 45182418d0..c52cac2753 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -17,7 +17,8 @@ - + + diff --git a/android/res/layout/keyboardinput.xml b/android/res/layout/keyboardinput.xml new file mode 100644 index 0000000000..124eda8fbe --- /dev/null +++ b/android/res/layout/keyboardinput.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 9320b2624d..b0d41f133d 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -3,4 +3,7 @@ Rockbox Rockbox +OK +Cancel +Rockbox Keyboard Input diff --git a/android/src/org/rockbox/HostCallback.java b/android/src/org/rockbox/HostCallback.java new file mode 100644 index 0000000000..0e69b3f283 --- /dev/null +++ b/android/src/org/rockbox/HostCallback.java @@ -0,0 +1,7 @@ +package org.rockbox; + +import android.content.Intent; + +public interface HostCallback { + public void onComplete(int resultCode, Intent data); +} diff --git a/android/src/org/rockbox/KeyboardActivity.java b/android/src/org/rockbox/KeyboardActivity.java new file mode 100644 index 0000000000..f32aae28f8 --- /dev/null +++ b/android/src/org/rockbox/KeyboardActivity.java @@ -0,0 +1,41 @@ +package org.rockbox; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.text.Editable; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +public class KeyboardActivity extends Activity { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LayoutInflater inflater=LayoutInflater.from(this); + View addView=inflater.inflate(R.layout.keyboardinput, null); + EditText input = (EditText) addView.findViewById(R.id.KbdInput); + input.setText(getIntent().getStringExtra("value")); + new AlertDialog.Builder(this) + .setTitle(R.string.KbdInputTitle) + .setView(addView) + .setIcon(R.drawable.icon) + .setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + EditText input = (EditText)((Dialog)dialog).findViewById(R.id.KbdInput); + Editable s = input.getText(); + getIntent().putExtra("value", s.toString()); + setResult(RESULT_OK, getIntent()); + finish(); + } + }) + .setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + setResult(RESULT_CANCELED, getIntent()); + finish(); + } + }) + .show(); + } +} diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java index f775597d30..9eed3f48dc 100644 --- a/android/src/org/rockbox/RockboxActivity.java +++ b/android/src/org/rockbox/RockboxActivity.java @@ -24,7 +24,9 @@ package org.rockbox; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; +import android.content.IntentFilter; import android.os.Bundle; +import android.util.Log; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; @@ -41,6 +43,7 @@ public class RockboxActivity extends Activity requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,WindowManager.LayoutParams.FLAG_FULLSCREEN); + final Activity thisActivity = this; final Intent intent = new Intent(this, RockboxService.class); /* prepare a please wait dialog in case we need * to wait for unzipping libmisc.so @@ -95,7 +98,8 @@ public class RockboxActivity extends Activity loadingdialog.dismiss(); if (rbservice.get_fb() == null) throw new IllegalStateException("FB NULL"); - setContentView(rbservice.get_fb()); + rbservice.set_activity(thisActivity); + setContentView(rbservice.get_fb()); rbservice.get_fb().invalidate(); } }); @@ -111,6 +115,7 @@ public class RockboxActivity extends Activity public void onResume() { + super.onResume(); if (isRockboxRunning()) { @@ -123,6 +128,7 @@ public class RockboxActivity extends Activity g.removeView(rbservice.get_fb()); setContentView(rbservice.get_fb()); } finally { + rbservice.set_activity(this); rbservice.get_fb().resume(); } } @@ -135,6 +141,7 @@ public class RockboxActivity extends Activity protected void onPause() { super.onPause(); + rbservice.set_activity(null); rbservice.get_fb().suspend(); } @@ -142,6 +149,7 @@ public class RockboxActivity extends Activity protected void onStop() { super.onStop(); + rbservice.set_activity(null); rbservice.get_fb().suspend(); } @@ -149,6 +157,29 @@ public class RockboxActivity extends Activity protected void onDestroy() { super.onDestroy(); + rbservice.set_activity(null); rbservice.get_fb().suspend(); } + + private HostCallback hostcallback = null; + public void waitForActivity(Intent i, HostCallback callback) + { + if (hostcallback != null) + { + LOG("Something has gone wrong"); + } + hostcallback = callback; + startActivityForResult(i, 0); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) + { + hostcallback.onComplete(resultCode, data); + hostcallback = null; + } + + private void LOG(CharSequence text) + { + Log.d("Rockbox", (String) text); + } } diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java index e90eb86dbd..20311a8790 100644 --- a/android/src/org/rockbox/RockboxFramebuffer.java +++ b/android/src/org/rockbox/RockboxFramebuffer.java @@ -118,12 +118,11 @@ public class RockboxFramebuffer extends View setFocusableInTouchMode(true); setClickable(true); requestFocus(); - /* make updates again, the underlying function will - * send an event */ set_lcd_active(1); } public native void set_lcd_active(int active); public native void touchHandler(boolean down, int x, int y); public native boolean buttonHandler(int keycode, boolean state); + } diff --git a/android/src/org/rockbox/RockboxKeyboardInput.java b/android/src/org/rockbox/RockboxKeyboardInput.java new file mode 100644 index 0000000000..b037f6c4bb --- /dev/null +++ b/android/src/org/rockbox/RockboxKeyboardInput.java @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Jonathan Gordon + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +package org.rockbox; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Intent; +import android.util.Log; + +public class RockboxKeyboardInput +{ + private BroadcastReceiver b; + private String result; + + public RockboxKeyboardInput() + { + result = null; + } + + public void kbd_input(String text) + { + RockboxActivity a = (RockboxActivity) RockboxService.get_instance().get_activity(); + Intent kbd = new Intent(a, KeyboardActivity.class); + kbd.putExtra("value", text); + a.waitForActivity(kbd, new HostCallback(){ + + @Override + public void onComplete(int resultCode, Intent data) { + if (resultCode == Activity.RESULT_OK) + { + result = data.getStringExtra("value"); + } + else { + result = ""; + } + } + }); + } + public String get_result() + { + return result; + } + + public boolean is_usable() + { + return RockboxService.get_instance().get_activity() != null; + } + + +} diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java index c403736c72..bbcdfec4a7 100644 --- a/android/src/org/rockbox/RockboxService.java +++ b/android/src/org/rockbox/RockboxService.java @@ -35,6 +35,7 @@ import java.util.TimerTask; 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; @@ -61,6 +62,7 @@ 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 = @@ -113,6 +115,16 @@ public class RockboxService extends Service fb = newfb; mRockboxRunning = true; } + + public Activity get_activity() + { + return current_activity; + } + public void set_activity(Activity a) + { + current_activity = a; + } + private void do_start(Intent intent) { diff --git a/apps/SOURCES b/apps/SOURCES index ad1003bb0d..cb5e6ef876 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -116,7 +116,11 @@ player/keyboard.c #ifdef HAVE_LCD_BITMAP recorder/bmp.c recorder/icons.c +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) +hosted/keyboard.c +#else recorder/keyboard.c +#endif recorder/peakmeter.c #if defined(HAVE_ALBUMART) || defined(HAVE_JPEG) recorder/resize.c diff --git a/apps/hosted/keyboard.c b/apps/hosted/keyboard.c new file mode 100644 index 0000000000..b395168156 --- /dev/null +++ b/apps/hosted/keyboard.c @@ -0,0 +1,86 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Jonathan Gordon + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" + +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) +#include +#include +#include +#include + +extern JNIEnv *env_ptr; +static jclass RockboxKeyboardInput_class = NULL; +static jobject RockboxKeyboardInput_instance; +static jmethodID kbd_inputfunc, kbd_result; + +static void kdb_init(void) +{ + JNIEnv e = *env_ptr; + jmethodID kbd_is_usable; + if (RockboxKeyboardInput_class == NULL) + { + /* get the class and its constructor */ + RockboxKeyboardInput_class = e->FindClass(env_ptr, "org/rockbox/RockboxKeyboardInput"); + jmethodID constructor = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, "", "()V"); + RockboxKeyboardInput_instance = e->NewObject(env_ptr, RockboxKeyboardInput_class, constructor); + kbd_inputfunc = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, + "kbd_input", "(Ljava/lang/String;)V"); + kbd_result = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, + "get_result", "()Ljava/lang/String;"); + } + /* need to get it every time incase the activity died/restarted */ + kbd_is_usable = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, + "is_usable", "()Z"); + while (!e->CallBooleanMethod(env_ptr, RockboxKeyboardInput_instance, kbd_is_usable)) + sleep(HZ/10); +} + +int kbd_input(char* text, int buflen) +{ + JNIEnv e = *env_ptr; + jstring str = e->NewStringUTF(env_ptr, text); + jobject ret; + const char* retchars; + kdb_init(); + + e->CallVoidMethod(env_ptr, RockboxKeyboardInput_instance, kbd_inputfunc, str); + + do { + sleep(HZ/10); + ret = e->CallObjectMethod(env_ptr, RockboxKeyboardInput_instance, kbd_result); + } while (!ret); + + e->ReleaseStringChars(env_ptr, str, NULL); + retchars = e->GetStringUTFChars(env_ptr, ret, 0); + if (retchars[0]) + snprintf(text, buflen, retchars); + e->ReleaseStringUTFChars(env_ptr, ret, retchars); + + return retchars[0]?0:1; /* return 0 on success */ +} + +int load_kbd(unsigned char* filename) +{ + (void)filename; + return 1; +} + +#endif