Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaClassWrapper: Allow handling exceptions (rather than just crashing) #102862

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/classes/JavaClassWrapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@

print(datetime.format(formatter))
[/codeblock]
[b]Warning:[/b] When calling Java methods, be sure to check [method JavaClassWrapper.get_exception] to check if the method threw an exception.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_exception">
<return type="JavaObject" />
<description>
Returns the Java exception from the last call into a Java class. If there was no exception, it will return [code]null[/code].
[b]Note:[/b] This method only works on Android. On every other platform, this method will always return [code]null[/code].
</description>
</method>
<method name="wrap">
<return type="JavaClass" />
<param index="0" name="name" type="String" />
Expand Down
1 change: 1 addition & 0 deletions platform/android/api/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void JavaObject::_bind_methods() {

void JavaClassWrapper::_bind_methods() {
ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap);
ClassDB::bind_method(D_METHOD("get_exception"), &JavaClassWrapper::get_exception);
}

#if !defined(ANDROID_ENABLED)
Expand Down
6 changes: 6 additions & 0 deletions platform/android/api/java_class_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ class JavaClassWrapper : public Object {
bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig);
#endif

Ref<JavaObject> exception;

Ref<JavaClass> _wrap(const String &p_class, bool p_allow_private_methods_access);

static JavaClassWrapper *singleton;
Expand All @@ -285,6 +287,10 @@ class JavaClassWrapper : public Object {
return _wrap(p_class, false);
}

Ref<JavaObject> get_exception() {
return exception;
}

#ifdef ANDROID_ENABLED
Ref<JavaClass> wrap_jclass(jclass p_class, bool p_allow_private_methods_access = false);
#endif
Expand Down
14 changes: 14 additions & 0 deletions platform/android/java_class_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,20 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
env->DeleteLocalRef(E);
}

jobject exception = env->ExceptionOccurred();
if (exception) {
env->ExceptionClear();

jclass java_class = env->GetObjectClass(exception);
Ref<JavaClass> java_class_wrapped = JavaClassWrapper::singleton->wrap_jclass(java_class);
env->DeleteLocalRef(java_class);

JavaClassWrapper::singleton->exception.instantiate(java_class_wrapped, exception);
env->DeleteLocalRef(exception);
} else {
JavaClassWrapper::singleton->exception.unref();
}

return success;
}

Expand Down