Android: handle native exceptions in Java (#223)

This commit is contained in:
Bektur 2021-11-08 16:19:58 +06:00 committed by GitHub
parent 96f80d2c30
commit a9cc034eaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 8 deletions

View File

@ -187,4 +187,8 @@ public class GameActivity extends NativeActivity {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(browserIntent); startActivity(browserIntent);
} }
public void finishGame(String exc) {
finish();
}
} }

View File

@ -59,7 +59,14 @@ void sanity_check_fn(const char *assertion, const char *file,
debug_stacks_print_to(errorstream); debug_stacks_print_to(errorstream);
#ifdef __ANDROID__
std::string capture = "An engine assumption failed: \"" + std::string(assertion) +
"\" in file: " + std::string(file) + ":" + std::to_string(line) +
" (" + std::string(function) + ")";
throw std::runtime_error(capture);
#else
abort(); abort();
#endif
} }
void fatal_error_fn(const char *msg, const char *file, void fatal_error_fn(const char *msg, const char *file,
@ -72,11 +79,18 @@ void fatal_error_fn(const char *msg, const char *file,
errorstream << std::endl << "In thread " << std::hex errorstream << std::endl << "In thread " << std::hex
<< thr_get_current_thread_id() << ":" << std::endl; << thr_get_current_thread_id() << ":" << std::endl;
errorstream << file << ":" << line << ": " << function errorstream << file << ":" << line << ": " << function
<< ": A fatal error occured: " << msg << std::endl; << ": A fatal error occurred: " << msg << std::endl;
debug_stacks_print_to(errorstream); debug_stacks_print_to(errorstream);
#ifdef __ANDROID__
std::string capture = "A fatal error occurred: \"" + std::string(msg) +
"\" in file: " + std::string(file) + ":" + std::to_string(line) +
" (" + std::string(function) + ")";
throw std::runtime_error(capture);
#else
abort(); abort();
#endif
} }
/* /*
@ -352,4 +366,3 @@ void debug_set_exception_handler()
SetUnhandledExceptionFilter(Win32ExceptionHandler); SetUnhandledExceptionFilter(Win32ExceptionHandler);
#endif #endif
} }

View File

@ -38,7 +38,6 @@ extern "C" void external_pause_game();
void android_main(android_app *app) void android_main(android_app *app)
{ {
int retval = 0;
porting::app_global = app; porting::app_global = app;
Thread::setName("Main"); Thread::setName("Main");
@ -49,15 +48,15 @@ void android_main(android_app *app)
free(argv[0]); free(argv[0]);
} catch (std::exception &e) { } catch (std::exception &e) {
errorstream << "Uncaught exception in main thread: " << e.what() << std::endl; errorstream << "Uncaught exception in main thread: " << e.what() << std::endl;
retval = -1; porting::finishGame(e.what());
} catch (...) { } catch (...) {
errorstream << "Uncaught exception in main thread!" << std::endl; errorstream << "Uncaught exception in main thread!" << std::endl;
retval = -1; porting::finishGame("Unknown error");
} }
porting::cleanupAndroid(); porting::cleanupAndroid();
infostream << "Shutting down." << std::endl; infostream << "Shutting down." << std::endl;
exit(retval); exit(0);
} }
/** /**
@ -232,7 +231,7 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint,
void openURIAndroid(const std::string &url) void openURIAndroid(const std::string &url)
{ {
jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI", jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI",
"(Ljava/lang/String;)V"); "(Ljava/lang/String;)V");
FATAL_ERROR_IF(url_open == nullptr, FATAL_ERROR_IF(url_open == nullptr,
"porting::openURIAndroid unable to find java openURI method"); "porting::openURIAndroid unable to find java openURI method");
jstring jurl = jnienv->NewStringUTF(url.c_str()); jstring jurl = jnienv->NewStringUTF(url.c_str());
@ -336,7 +335,30 @@ float getDisplayDensity()
return value; return value;
} }
v2u32 getDisplaySize() { v2u32 getDisplaySize()
{
return porting::getWindowSize(); return porting::getWindowSize();
} }
void finishGame(const std::string &exc)
{
if (jnienv->ExceptionCheck())
jnienv->ExceptionClear();
jmethodID finishMe;
try {
finishMe = jnienv->GetMethodID(nativeActivity,
"finishGame", "(Ljava/lang/String;)V");
} catch (...) {
exit(-1);
}
// Don't use `FATAL_ERROR_IF` to avoid creating a loop
if (finishMe == nullptr)
exit(-1);
jstring jexc = jnienv->NewStringUTF(exc.c_str());
jnienv->CallVoidMethod(app_global->activity->clazz, finishMe, jexc);
}
} }

View File

@ -86,4 +86,9 @@ std::string getInputDialogValue();
* notify java on game exit * notify java on game exit
*/ */
void notifyExitGame(); void notifyExitGame();
/**
* call Android function to finish
*/
void finishGame(const std::string &exc);
} }