From 4be7c91cd900b03faeea7f65bb24c4e4e4aca0dc Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Wed, 7 Sep 2022 14:25:22 -0700 Subject: [PATCH] Fix issue causing the project manager to crash because of missing path argument In the process, the initialization logic is updated to show an error message and gracefully close the engine when setup errors occur. --- editor/editor_node.cpp | 8 ++++-- .../android/java/lib/res/values/strings.xml | 2 ++ .../lib/src/org/godotengine/godot/Godot.java | 28 +++++++++++++++++-- .../src/org/godotengine/godot/GodotLib.java | 2 +- platform/android/java_godot_lib_jni.cpp | 9 +++--- platform/android/java_godot_lib_jni.h | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3d76ee8b415..b7b050364d5 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3062,8 +3062,12 @@ void EditorNode::_discard_changes(const String &p_str) { for (int i = 0; i < forwardable_args.size(); i++) { args.push_back(forwardable_args[i]); } - args.push_back("--path"); - args.push_back(exec.get_base_dir()); + + String exec_base_dir = exec.get_base_dir(); + if (!exec_base_dir.empty()) { + args.push_back("--path"); + args.push_back(exec_base_dir); + } args.push_back("--project-manager"); OS::ProcessID pid = 0; diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml index 010006b81ea..f5a4ab1071b 100644 --- a/platform/android/java/lib/res/values/strings.xml +++ b/platform/android/java/lib/res/values/strings.xml @@ -12,6 +12,8 @@ Resume Download Cancel Cancel Verification + Error! + Unable to setup the Godot Engine! Aborting… diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 8913e0faf56..e680e0433ba 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -57,6 +57,7 @@ import android.content.SharedPreferences.Editor; import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.hardware.Sensor; @@ -71,6 +72,7 @@ import android.os.Looper; import android.os.Messenger; import android.os.VibrationEffect; import android.os.Vibrator; +import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.Surface; @@ -88,6 +90,7 @@ import androidx.annotation.CallSuper; import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; import com.google.android.vending.expansion.downloader.DownloadProgressInfo; @@ -112,6 +115,8 @@ import java.util.Locale; import javax.microedition.khronos.opengles.GL10; public class Godot extends Fragment implements SensorEventListener, IDownloaderClient { + private static final String TAG = Godot.class.getSimpleName(); + static final int MAX_SINGLETONS = 64; private IStub mDownloaderClientStub; private TextView mStatusText; @@ -376,7 +381,12 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC final String[] current_command_line = command_line; mView.queueEvent(() -> { - GodotLib.setup(current_command_line); + if (!GodotLib.setup(current_command_line)) { + godot_initialized = false; + Log.e(TAG, "Unable to setup the Godot engine! Aborting..."); + alert(R.string.error_engine_setup_message, R.string.text_error_title, this::forceQuit); + return; + } // Must occur after GodotLib.setup has completed. for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { @@ -460,13 +470,27 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } public void alert(final String message, final String title) { + alert(message, title, null); + } + + private void alert(@StringRes int messageResId, @StringRes int titleResId, @Nullable Runnable okCallback) { + Resources res = getResources(); + alert(res.getString(messageResId), res.getString(titleResId), okCallback); + } + + private void alert(final String message, final String title, @Nullable Runnable okCallback) { final Activity activity = getActivity(); runOnUiThread(() -> { AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setMessage(message).setTitle(title); builder.setPositiveButton( "OK", - (dialog, id) -> dialog.cancel()); + (dialog, id) -> { + if (okCallback != null) { + okCallback.run(); + } + dialog.cancel(); + }); AlertDialog dialog = builder.create(); dialog.show(); }); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index cf34b95c766..82681e13244 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -65,7 +65,7 @@ public class GodotLib { * Invoked on the GL thread to complete setup for the Godot native layer logic. * @param p_cmdline Command line arguments used to configure Godot native layer components. */ - public static native void setup(String[] p_cmdline); + public static native boolean setup(String[] p_cmdline); /** * Invoked on the GL thread when the underlying Android surface has changed size. diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 6b06bff615d..b013da86de6 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -165,7 +165,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env } } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) { +JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) { setup_android_thread(); const char **cmdline = nullptr; @@ -175,10 +175,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc cmdlen = env->GetArrayLength(p_cmdline); if (cmdlen) { cmdline = (const char **)memalloc((cmdlen + 1) * sizeof(const char *)); - ERR_FAIL_NULL_MSG(cmdline, "Out of memory."); + ERR_FAIL_NULL_V_MSG(cmdline, false, "Out of memory."); cmdline[cmdlen] = nullptr; j_cmdline = (jstring *)memalloc(cmdlen * sizeof(jstring)); - ERR_FAIL_NULL_MSG(j_cmdline, "Out of memory."); + ERR_FAIL_NULL_V_MSG(j_cmdline, false, "Out of memory."); for (int i = 0; i < cmdlen; i++) { jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i); @@ -203,12 +203,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc // Note: --help and --version return ERR_HELP, but this should be translated to 0 if exit codes are propagated. if (err != OK) { - return; // should exit instead and print the error + return false; } java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity())); ClassDB::register_class(); _initialize_java_modules(); + return true; } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height) { diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 6c4d11272b2..3c99314b5ee 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -39,7 +39,7 @@ extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline); +JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ttsCallback(JNIEnv *env, jclass clazz, jint event, jint id, jint pos);