diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template index d8fb9326ea3..daaf847f116 100644 --- a/platform/android/AndroidManifest.xml.template +++ b/platform/android/AndroidManifest.xml.template @@ -36,4 +36,9 @@ $$ADD_APPLICATION_CHUNKS$$ + + diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index a10d7876f49..c00199dad6d 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -38,6 +38,7 @@ import android.app.AlertDialog; import android.app.PendingIntent; import android.content.ClipData; import android.content.ClipboardManager; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -318,6 +319,23 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC }); } + public void restart() { + // HACK: + // + // Currently it's very hard to properly deinitialize Godot on Android to restart the game + // from scratch. Therefore, we need to kill the whole app process and relaunch it. + // + // Restarting only the activity, wouldn't be enough unless it did proper cleanup (including + // releasing and reloading native libs or resetting their state somehow and clearing statics). + // + // Using instrumentation is a way of making the whole app process restart, because Android + // will kill any process of the same package which was already running. + // + Bundle args = new Bundle(); + args.putParcelable("intent", mCurrentIntent); + startInstrumentation(new ComponentName(Godot.this, GodotInstrumentation.class), null, args); + } + public void alert(final String message, final String title) { final Activity activity = this; runOnUiThread(new Runnable() { @@ -415,7 +433,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); - GodotLib.initialize(this, io.needsReloadHooks(), getAssets(), use_apk_expansion); + GodotLib.initialize(this, getAssets(), use_apk_expansion); result_callback = null; @@ -921,10 +939,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC // Audio /** - * The download state should trigger changes in the UI --- it may be useful - * to show the state as being indeterminate at times. This sample can be - * considered a guideline. - */ + * The download state should trigger changes in the UI --- it may be useful + * to show the state as being indeterminate at times. This sample can be + * considered a guideline. + */ @Override public void onDownloadStateChanged(int newState) { setState(newState); diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java index 85bba8bb4c5..1b2ff613143 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java @@ -500,11 +500,6 @@ public class GodotIO { return (int)(metrics.density * 160f); } - public boolean needsReloadHooks() { - - return false; - } - public void showKeyboard(String p_existing_text) { if (edit != null) edit.showKeyboard(p_existing_text); diff --git a/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java b/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java new file mode 100644 index 00000000000..0466f380e84 --- /dev/null +++ b/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java @@ -0,0 +1,50 @@ +/*************************************************************************/ +/* GodotInstrumentation.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +package org.godotengine.godot; + +import android.app.Instrumentation; +import android.content.Intent; +import android.os.Bundle; + +public class GodotInstrumentation extends Instrumentation { + private Intent intent; + + @Override + public void onCreate(Bundle arguments) { + intent = arguments.getParcelable("intent"); + start(); + } + + @Override + public void onStart() { + startActivitySync(intent); + } +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java index 29e7918645f..dc381f35d4e 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -45,9 +45,9 @@ public class GodotLib { * @param height the current view height */ - public static native void initialize(Godot p_instance, boolean need_reload_hook, Object p_asset_manager, boolean use_apk_expansion); + public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); public static native void setup(String[] p_cmdline); - public static native void resize(int width, int height, boolean reload); + public static native void resize(int width, int height); public static native void newcontext(boolean p_32_bits); public static native void back(); public static native void step(); diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java index ba8e8bd07bb..ccf78f26f32 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -79,7 +79,6 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { private Context ctx; private GodotIO io; - private static boolean firsttime = true; private static boolean use_gl3 = false; private static boolean use_32 = false; private static boolean use_debug_opengl = false; @@ -97,10 +96,8 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { activity = p_activity; - if (!p_io.needsReloadHooks()) { - //will only work on SDK 11+!! - setPreserveEGLContextOnPause(true); - } + setPreserveEGLContextOnPause(true); + mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext()); mInputManager.registerInputDeviceListener(this, null); init(false, 16, 0); @@ -718,8 +715,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { public void onSurfaceChanged(GL10 gl, int width, int height) { - GodotLib.resize(width, height, !firsttime); - firsttime = false; + GodotLib.resize(width, height); for (int i = 0; i < Godot.singleton_count; i++) { Godot.singletons[i].onGLSurfaceChanged(gl, width, height); } diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 53c909da889..7adfec0ebb4 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -599,6 +599,7 @@ static jobject godot_io; typedef void (*GFXInitFunc)(void *ud, bool gl2); static jmethodID _on_video_init = 0; +static jmethodID _restart = 0; static jobject _godot_instance; static jmethodID _openURI = 0; @@ -757,7 +758,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei virtual_keyboard_height = p_height; } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) { initialized = true; @@ -783,6 +784,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en godot_io = gob; _on_video_init = env->GetMethodID(cls, "onVideoInit", "()V"); + _restart = env->GetMethodID(cls, "restart", "()V"); _setKeepScreenOn = env->GetMethodID(cls, "setKeepScreenOn", "(Z)V"); _alertDialog = env->GetMethodID(cls, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); _getGLESVersionCode = env->GetMethodID(cls, "getGLESVersionCode", "()I"); @@ -821,7 +823,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en } os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_user_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _get_gles_version_code, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, _set_clipboard, _get_clipboard, p_use_apk_expansion); - os_android->set_need_reload_hooks(p_need_reload_hook); char wd[500]; getcwd(wd, 500); @@ -932,7 +933,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo _initialize_java_modules(); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height) { if (os_android) os_android->set_display_size(Size2(width, height)); @@ -941,12 +942,15 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) { if (os_android) { - os_android->set_context_is_16_bits(!p_32_bits); - } - - if (os_android && step > 0) { - - os_android->reload_gfx(); + if (step == 0) { + // During startup + os_android->set_context_is_16_bits(!p_32_bits); + } else { + // GL context recreated because it was lost; restart app to let it reload everything + os_android->main_loop_end(); + env->CallVoidMethod(_godot_instance, _restart); + step = -1; // Ensure no further steps are attempted + } } } @@ -958,6 +962,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, job } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) { + if (step == -1) + return; + if (step == 0) { // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id, diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index e8d0d55bb30..105872365ef 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -35,9 +35,9 @@ #include extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 8c4531213fe..7fac5dd448f 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -548,14 +548,6 @@ void OS_Android::set_display_size(Size2 p_size) { default_videomode.height = p_size.y; } -void OS_Android::reload_gfx() { - - if (gfx_init_func) - gfx_init_func(gfx_init_ud, use_gl2); - //if (rasterizer) - // rasterizer->reload_vram(); -} - Error OS_Android::shell_open(String p_uri) { if (open_uri_func) @@ -607,11 +599,6 @@ int OS_Android::get_screen_dpi(int p_screen) const { return 160; } -void OS_Android::set_need_reload_hooks(bool p_needs_them) { - - use_reload_hooks = p_needs_them; -} - String OS_Android::get_user_data_dir() const { if (data_dir_cache != String()) @@ -765,7 +752,6 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI set_screen_orientation_func = p_screen_orient; set_keep_screen_on_func = p_set_keep_screen_on_func; alert_func = p_alert_func; - use_reload_hooks = false; Vector loggers; loggers.push_back(memnew(AndroidLogger)); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 1e5b89e24d4..cfd92d3420d 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -94,7 +94,6 @@ private: void *gfx_init_ud; bool use_gl2; - bool use_reload_hooks; bool use_apk_expansion; bool use_16bits_fbo; @@ -203,10 +202,8 @@ public: void set_opengl_extensions(const char *p_gl_extensions); void set_display_size(Size2 p_size); - void reload_gfx(); void set_context_is_16_bits(bool p_is_16); - void set_need_reload_hooks(bool p_needs_them); virtual void set_screen_orientation(ScreenOrientation p_orientation); virtual Error shell_open(String p_uri);