From ba6b66fbb61bed2f0e510d84d28807bb31d6f667 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 6 Dec 2025 21:08:23 +0100 Subject: [PATCH] android: Fix crash when setting window title on wrong thread --- makepanda/makepanda.py | 2 ++ panda/src/android/PandaActivity.java | 12 ++++++++++++ panda/src/android/config_android.cxx | 17 ++++++----------- panda/src/android/config_android.h | 4 +--- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 096388acd4..7101b473d7 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -4946,12 +4946,14 @@ if GetTarget() == 'android': TargetAdd('org/panda3d/android/NativeOStream.class', opts=OPTS, input='NativeOStream.java') TargetAdd('org/panda3d/android/PandaActivity.class', opts=OPTS, input='PandaActivity.java') TargetAdd('org/panda3d/android/PandaActivity$1.class', opts=OPTS+['DEPENDENCYONLY'], input='PandaActivity.java') + TargetAdd('org/panda3d/android/PandaActivity$2.class', opts=OPTS+['DEPENDENCYONLY'], input='PandaActivity.java') TargetAdd('org/panda3d/android/PythonActivity.class', opts=OPTS, input='PythonActivity.java') TargetAdd('classes.dex', input='org/panda3d/android/NativeIStream.class') TargetAdd('classes.dex', input='org/panda3d/android/NativeOStream.class') TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity.class') TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$1.class') + TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$2.class') TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity.class') TargetAdd('p3android_composite1.obj', opts=OPTS, input='p3android_composite1.cxx') diff --git a/panda/src/android/PandaActivity.java b/panda/src/android/PandaActivity.java index e3d6836407..4c7e64b4f8 100644 --- a/panda/src/android/PandaActivity.java +++ b/panda/src/android/PandaActivity.java @@ -159,6 +159,18 @@ public class PandaActivity extends NativeActivity { return getCacheDir().toString(); } + /** + * Sets the window title. + */ + public void setWindowTitle(final CharSequence title) { + final PandaActivity activity = this; + runOnUiThread(new Runnable() { + public void run() { + activity.setTitle(title); + } + }); + } + /** * Shows a pop-up notification. */ diff --git a/panda/src/android/config_android.cxx b/panda/src/android/config_android.cxx index 88ddba3c50..53c22c7b73 100644 --- a/panda/src/android/config_android.cxx +++ b/panda/src/android/config_android.cxx @@ -27,11 +27,9 @@ jmethodID jni_PandaActivity_readBitmap; jmethodID jni_PandaActivity_createBitmap; jmethodID jni_PandaActivity_compressBitmap; jmethodID jni_PandaActivity_showToast; +jmethodID jni_PandaActivity_setWindowTitle; jmethodID jni_PandaActivity_findLibrary; -jclass jni_Activity; -jmethodID jni_Activity_setTitle; - jclass jni_BitmapFactory_Options; jfieldID jni_BitmapFactory_Options_outWidth; jfieldID jni_BitmapFactory_Options_outHeight; @@ -81,17 +79,15 @@ jint JNI_OnLoad(JavaVM *jvm, void *reserved) { jni_PandaActivity_compressBitmap = env->GetStaticMethodID(jni_PandaActivity, "compressBitmap", "(Landroid/graphics/Bitmap;IIJ)Z"); + jni_PandaActivity_setWindowTitle = env->GetMethodID(jni_PandaActivity, + "setWindowTitle", "(Ljava/lang/CharSequence;)V"); + jni_PandaActivity_showToast = env->GetMethodID(jni_PandaActivity, "showToast", "(Ljava/lang/String;I)V"); jni_PandaActivity_findLibrary = env->GetMethodID(jni_PandaActivity, "findLibrary", "(Ljava/lang/String;)Ljava/lang/String;"); - jni_Activity = env->FindClass("android/app/Activity"); - jni_Activity = (jclass) env->NewGlobalRef(jni_Activity); - jni_Activity_setTitle = env->GetMethodID(jni_Activity, - "setTitle", "(Ljava/lang/CharSequence;)V"); - jni_BitmapFactory_Options = env->FindClass("android/graphics/BitmapFactory$Options"); jni_BitmapFactory_Options = (jclass) env->NewGlobalRef(jni_BitmapFactory_Options); @@ -130,7 +126,6 @@ void JNI_OnUnload(JavaVM *jvm, void *reserved) { nassertv(env != nullptr); env->DeleteGlobalRef(jni_PandaActivity); - env->DeleteGlobalRef(jni_Activity); env->DeleteGlobalRef(jni_BitmapFactory_Options); // These will no longer work without JNI, so unregister them. @@ -174,14 +169,14 @@ Filename android_find_library(ANativeActivity *activity, const std::string &lib) * Sets the window title of the activity. */ void android_set_title(ANativeActivity *activity, const std::string &title) { - nassertv(jni_Activity_setTitle); + nassertv(jni_PandaActivity_setWindowTitle); Thread *thread = Thread::get_current_thread(); JNIEnv *env = thread->get_jni_env(); nassertv(env != nullptr); jstring jmsg = env->NewStringUTF(title.c_str()); - env->CallVoidMethod(activity->clazz, jni_Activity_setTitle, jmsg); + env->CallVoidMethod(activity->clazz, jni_PandaActivity_setWindowTitle, jmsg); env->DeleteLocalRef(jmsg); } diff --git a/panda/src/android/config_android.h b/panda/src/android/config_android.h index 286e517a39..94a417c104 100644 --- a/panda/src/android/config_android.h +++ b/panda/src/android/config_android.h @@ -33,11 +33,9 @@ extern jmethodID jni_PandaActivity_readBitmapHeader; extern jmethodID jni_PandaActivity_readBitmap; extern jmethodID jni_PandaActivity_createBitmap; extern jmethodID jni_PandaActivity_compressBitmap; +extern jmethodID jni_PandaActivity_setWindowTitle; extern jmethodID jni_PandaActivity_showToast; -extern jclass jni_Activity; -extern jmethodID jni_Activity_setTitle; - extern jclass jni_BitmapFactory_Options; extern jfieldID jni_BitmapFactory_Options_outWidth; extern jfieldID jni_BitmapFactory_Options_outHeight;