Android: handle native exceptions in Java (#223)
This commit is contained in:
parent
96f80d2c30
commit
a9cc034eaf
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user