Normally, a Bevy application can exit with AppExit, like:
fn exit_system(mut exit_event: MessageWriter<AppExit>) {
exit_event.write(AppExit::Success);
}
But on Android, that is not enough and can cause the app fails to reopen. To completely exit the Bevy application on Android, we need to exit on the Android side too.
.--------------------------------------. .------------------------------.
| Bevy | | Android |
| .------------. .------------. | | .------------. |
| | system | | main | | | | MainActivity | |
| '-----+-+----' '-----+-+----' | | '-----+-+----' |
| | | AppExit | | | | | | |
| +-+--------------->| | | | | | |
| | | exitAppActivity | | |
| +-+---------------------------->| | |
| | | | +---. |
| | | | | | finishAffinity |
| | | | | | |
| | | +-+<--' |
| | | |
'--------------------------------------' '------------------------------'
Start with the Android example: https://github.com/bevyengine/bevy/tree/main/examples/mobile/android_example
Java wrapper
In MainActivity.java, add a function for exit the app, then Bevy app can call it in the Rust side:
...
import android.os.Handler;
public class MainActivity extends GameActivity {
...
// This function will exit the Android app
public void exitAppActivity() {
// `finishAffinity` needs to be run in main thread
new Handler().post(new Runnable() {
@Override
public void run() {
MainActivity.this.finishAffinity();
}
});
}
}Bevy app
Add dependency jni for android target in Cargo.toml.
[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21"
In Bevy app, call the Android function exitAppActivity after the app.run() has finished:
#[bevy_main]
fn main() {
let mut app = App::new();
...
app.run();
// Exit the Android app after Bevy job is finished
#[cfg(target_os = "android")]
exit_android_app();
}
#[cfg(target_os = "android")]
fn exit_android_app() -> anyhow::Result<()> {
let ctx = bevy::android::ANDROID_APP.get().expect("ANDROID_APP should be defined");
let vm = unsafe { jni::JavaVM::from_raw(ctx.vm_as_ptr() as *mut *const jni::sys::JNIInvokeInterface_) }?;
let activity = unsafe { jni::objects::JObject::from_raw(ctx.activity_as_ptr() as *mut jni::sys::_jobject) };
let mut env = vm.attach_current_thread()?;
// Call MainActivity::exitAppActivity
env.call_method(activity, "exitAppActivity", "()V", &[])?;
Ok(())
}
Comments