My Quick Notes

Ain't Nobody Got Time to Read

April 22, 2025

Làm thế nào để hoàn toàn thoát Bevy app trên Android

Thông thường, chúng ta có thể dừng và thoát một chương trình Bevy bằng việc gửi AppExit. Ví dụ:

fn exit_system(mut exit_event: MessageWriter<AppExit>) {
    exit_event.write(AppExit::Success);
}

Nhưng trên Android, app sẽ không được thoát hoàn toàn và bị lỗi không thể mở lại được. Để hoàn toàn thoát chương trình Bevy trên Android, chúng ta cần phải đóng ứng dụng từ cả phía Android.

 .--------------------------------------.           .------------------------------.
|                  Bevy                  |         |            Android             |
|   .------------.     .------------.    |         |   .------------.               |
|  |    system    |   |     main     |   |         |  | MainActivity |              |
|   '-----+-+----'     '-----+-+----'    |         |   '-----+-+----'               |
|         | |    AppExit     | |         |         |         | |                    |
|         +-+--------------->| |         |         |         | |                    |
|                            | |     exitAppActivity         | |                    |
|                            +-+---------------------------->| |                    |
|                                        |         |         | +---.                |
|                                        |         |         | |   | finishAffinity |
|                                        |         |         | |   |                |
|                                        |         |         +-+<--'                |
|                                        |         |                                |
 '--------------------------------------'           '------------------------------'

Ví dụ để chạy Bevy app trên Android có thể tham khảo ở đây: https://github.com/bevyengine/bevy/tree/main/examples/mobile/android_example

Java wrapper

Trong MainActivity trong MainActivity.java, tạo một hàm để đóng app. Hàm này sẽ được gọi từ phía Rust code:

...
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

Trong file Cargo.toml, thêm dependency cho target android:

[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21"

Trong Bevy app, gọi hàm Android exitAppActivity đã được định nghĩa ở phía trên:

#[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(())
}
Bài trướcVim - Lưu file với quyền root mà không cần mở lại file
Bài tiếpBuckle spring keyboard sound on Fedora Wayland

Bình luận