diff --git a/libraries/liblambdanative/system.c b/libraries/liblambdanative/system.c index db646096..4a932b74 100644 --- a/libraries/liblambdanative/system.c +++ b/libraries/liblambdanative/system.c @@ -150,10 +150,25 @@ static void find_directories() #endif #if defined(ANDROID) // we put files on the sdcard, that's the only sane place (?) + extern char* android_getFilesDir(); char path[1024]; +#if 0 sprintf(path,"/sdcard/%s", SYS_APPNAME); sys_appdir=strdup(path); sys_dir=strdup(path); +#endif +#if 0 + sprintf(path,"%s/system", android_getFilesDir()); + sys_dir=strdup(path); + sprintf(path,"%s/data", android_getFilesDir()); + sys_appdir=strdup(path); +#endif +#if 1 + sprintf(path,"/sdcard/%s", SYS_APPNAME); + sys_dir=strdup(path); + sys_appdir=android_getFilesDir(); +#endif + #endif #if defined(BB10) || defined(PLAYBOOK) char path[1024], cwd[1024]; diff --git a/loaders/android/bootstrap.c.in b/loaders/android/bootstrap.c.in index 267670d3..b7bdddc3 100644 --- a/loaders/android/bootstrap.c.in +++ b/loaders/android/bootstrap.c.in @@ -62,11 +62,23 @@ void Java_@SYS_PACKAGE_UNDERSCORE@_@SYS_APPNAME@_nativeEvent(JNIEnv* e, jobject // JNI Hooks and Global Objects static jobject globalObj=NULL; static JavaVM* s_vm = NULL; +static const char* app_directory_files = NULL; +static const char* app_code_path = NULL; -void Java_@SYS_PACKAGE_UNDERSCORE@_@SYS_APPNAME@_nativeInstanceInit(JNIEnv* env, jobject thiz){ - globalObj = (*env)->NewGlobalRef(env,thiz); +void Java_@SYS_PACKAGE_UNDERSCORE@_@SYS_APPNAME@_nativeInstanceInit(JNIEnv* env, jobject thiz, jstring codePath, jstring directoryFiles){ + + globalObj = (*env)->NewGlobalRef(env,thiz); + app_directory_files = strdup((*env)->GetStringUTFChars(env, directoryFiles, 0)); + (*env)->ReleaseStringUTFChars(env, directoryFiles, NULL); + app_code_path = strdup((*env)->GetStringUTFChars(env, codePath, 0)); + (*env)->ReleaseStringUTFChars(env, codePath, NULL); } +char* android_getFilesDir() { return (char*) app_directory_files; } +char* android_getPackageCodePath() { return (char*) app_code_path; } + +char* android_getFilesDir_info_get() { return android_getFilesDir(); } + jint JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv *env; s_vm=vm; @@ -77,19 +89,38 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv* GetJNIEnv(){ int error=0; JNIEnv* env = NULL; - if (s_vm) error=(*s_vm)->AttachCurrentThread(s_vm, &env, NULL); - if (!error&&(*env)->ExceptionCheck(env)) return NULL; + /* static `env` does NOT work! Once in a while we should ponder if + it still does not work or why. + + if(env) { + if((*env)->ExceptionCheck(env)) (*env)->ExceptionClear(env); + return env; + } + */ + if(s_vm) error=(*s_vm)->AttachCurrentThread(s_vm, &env, NULL); + //if(!error&&(*env)->ExceptionCheck(env)) return NULL; + if(!error) error = JNI_forward_exception_to_gambit(env); return (error?NULL:env); } +int JNI_forward_exception_to_gambit(JNIEnv*env) { + // TBD: actually forward, not only clear! + if((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); + return 1; + } + return 0; +} + // url launcher ffi void android_launch_url(char* urlstring){ JNIEnv *env = GetJNIEnv(); - jstring jurlstring = (*env)->NewStringUTF(env,urlstring); if (env&&globalObj) { + jstring jurlstring = (*env)->NewStringUTF(env, urlstring); jclass cls = (*env)->FindClass(env, "@SYS_PACKAGE_SLASH@/@SYS_APPNAME@"); - jmethodID method = (*env)->GetMethodID(env, cls, "openURL", "(Ljava/lang/String;)V"); - (*env)->CallVoidMethod(env, globalObj, method, jurlstring); + jmethodID method = cls ? (*env)->GetMethodID(env, cls, "openURL", "(Ljava/lang/String;)V") : NULL; + if(method) (*env)->CallVoidMethod(env, globalObj, method, jurlstring); + JNI_forward_exception_to_gambit(env); } } diff --git a/loaders/android/bootstrap.java.in b/loaders/android/bootstrap.java.in index dd99563d..d96ac4e1 100644 --- a/loaders/android/bootstrap.java.in +++ b/loaders/android/bootstrap.java.in @@ -126,20 +126,42 @@ public class @SYS_APPNAME@ extends Activity implements @ANDROID_JAVA_IMPLEMENTS@ } } + private android.view.View current_ContentView = null; + @Override + public void setContentView(android.view.View view) { + if(current_ContentView != view) { + // Note: this is a bit brain deas as it ONLY handles GLSurfaceView + if(current_ContentView instanceof android.opengl.GLSurfaceView) { + ((android.opengl.GLSurfaceView)current_ContentView).onPause(); + } + android.view.ViewParent parent0 = view.getParent(); + if(parent0 instanceof android.view.ViewGroup) { + android.view.ViewGroup parent = (android.view.ViewGroup) parent0; + if(parent!=null) { parent.removeView(current_ContentView); } + } + current_ContentView = view; + super.setContentView(current_ContentView); + if(current_ContentView instanceof android.opengl.GLSurfaceView) { + ((android.opengl.GLSurfaceView)current_ContentView).onResume(); + } + } + } + @Override protected void onCreate(Bundle savedInstanceState) { + current_ContentView = null; super.onCreate(savedInstanceState); Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { final String TAG = "@SYS_PACKAGE_DOT@"; - Log.e(TAG, e.toString()); + Log.e(TAG, e.toString()); try { Thread.sleep(1000); } catch (Exception ex) { } System.exit(1); } }); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - this.requestWindowFeature(Window.FEATURE_NO_TITLE); + this.requestWindowFeature(Window.FEATURE_NO_TITLE); // make sure volume controls control media this.setVolumeControlStream(AudioManager.STREAM_MUSIC); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, @@ -147,7 +169,7 @@ public class @SYS_APPNAME@ extends Activity implements @ANDROID_JAVA_IMPLEMENTS@ // prevent sleep getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mGLView = new xGLSurfaceView(this); - setContentView(mGLView); + // NOTE: we MAY better move the following lines BELOW nativeInstanceInit mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); checkOrRequestPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE); @@ -155,13 +177,14 @@ public class @SYS_APPNAME@ extends Activity implements @ANDROID_JAVA_IMPLEMENTS@ // Additions needed by modules, e.g. gps @ANDROID_JAVA_ONCREATE@ - // start EVENT_IDLE + nativeInstanceInit(getApplicationContext().getPackageCodePath().toString(), getFilesDir().toString()); + // start EVENT_IDLE + setContentView(mGLView); // MUST NOT run before nativeInstanceInit completed if(idle_tmScheduleRate > 0) idle_tm.scheduleAtFixedRate(idle_task, 0, idle_tmScheduleRate); - - nativeInstanceInit(); } - @Override + @Override protected void onDestroy() { + setContentView(mGLView); @ANDROID_JAVA_ONDESTROY@ nativeEvent(14,0,0); // EVENT_CLOSE nativeEvent(127,0,0); // EVENT_TERMINATE @@ -173,19 +196,19 @@ public class @SYS_APPNAME@ extends Activity implements @ANDROID_JAVA_IMPLEMENTS@ } @Override protected void onPause() { - super.onPause(); // Additions needed by modules, e.g. gps @ANDROID_JAVA_ONPAUSE@ - if (!isFinishing()) { + if (!isFinishing() && current_ContentView==mGLView) { mGLView.onPause(); } + super.onPause(); } @Override protected void onResume() { super.onResume(); + if(current_ContentView==mGLView) { mGLView.onResume(); } // Additions needed by modules, e.g. gps @ANDROID_JAVA_ONRESUME@ - mGLView.onResume(); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { @@ -220,13 +243,13 @@ public class @SYS_APPNAME@ extends Activity implements @ANDROID_JAVA_IMPLEMENTS@ } } - native void nativeInstanceInit(); + native void nativeInstanceInit(String packageCodePath, String filesDir); } class xGLSurfaceView extends GLSurfaceView { public xGLSurfaceView(Context context) { super(context); - setFocusable(true); + setFocusable(true); setFocusableInTouchMode(true); renderer = new myRenderer(); setRenderer(renderer); @@ -241,23 +264,23 @@ class xGLSurfaceView extends GLSurfaceView { case MotionEvent.ACTION_UP: t=4; break; case MotionEvent.ACTION_POINTER_UP: t=4; break; } - if (t>0) { + if (t>0) { final int n=event.getPointerCount(); final int t0=t; final int id0=event.getPointerId(0); final int x0=(int)event.getX(0); final int y0=(int)event.getY(0); if (n>1) { // MultiTouch - queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(18,id0,0); }}); + queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(18,id0,0); }}); } - queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(t0,x0,y0); }}); + queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(t0,x0,y0); }}); if (n>1) { // MultiTouch final int id1=event.getPointerId(1); final int x1=(int)event.getX(1); final int y1=(int)event.getY(1); - queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(18,id1,0); }}); - queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(t0,x1,y1); }}); - } + queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(18,id1,0); }}); + queueEvent(new Runnable(){ public void run() { renderer.pointerEvent(t0,x1,y1); }}); + } } return true; } @@ -295,7 +318,7 @@ class xGLSurfaceView extends GLSurfaceView { } if (t>0) { queueEvent(new Runnable(){ public void run() { - renderer.nativeEvent(t,x,y); }}); + renderer.nativeEvent(t,x,y); }}); } return true; } @@ -311,15 +334,15 @@ class xGLSurfaceView extends GLSurfaceView { myRenderer renderer; } class myRenderer implements GLSurfaceView.Renderer { - public void onSurfaceCreated(GL10 gl, EGLConfig config) { + public void onSurfaceCreated(GL10 gl, EGLConfig config) { } public void onSurfaceChanged(GL10 gl, int w, int h) { gl.glViewport(0, 0, w, h); width=(float)w; height=(float)h; nativeEvent(127,w,h); // EVENT_INIT } - public void onDrawFrame(GL10 gl) { - nativeEvent(15,0,0); // EVENT_REDRAW + public void onDrawFrame(GL10 gl) { + nativeEvent(15,0,0); // EVENT_REDRAW } public void pointerEvent(int t, int x, int y) { nativeEvent(t,x,(int)height-y); } public float width,height; diff --git a/modules/config/config.scm b/modules/config/config.scm index 6880f1da..044232f1 100644 --- a/modules/config/config.scm +++ b/modules/config/config.scm @@ -94,4 +94,18 @@ end-of-c-declare (gambit-c (if (string=? (system-platform) "android") (##heartbeat-interval-set! -1.))) (else (if (string=? (system-platform) "android") (##set-heartbeat-interval! -1.)))) +(cond-expand + (android + (c-declare #<