mirror of
https://github.com/rust-mobile/android-activity.git
synced 2026-07-04 05:47:26 +00:00
Update READMEs
This commit is contained in:
@@ -1,13 +1,23 @@
|
||||
This project includes a number of Android "glue" crates for native Rust development
|
||||
(comparable to [`android_native_app_glue.c`][ndk_concepts] which supports C/C++
|
||||
applications).
|
||||
# Overview
|
||||
|
||||
These glue crates provide a way to load a `cdylib` via the `onCreate` method of
|
||||
`android-activity` provides a "glue" layer for building native Rust
|
||||
applications on Android, supporting multiple [`Activity`] base classes.
|
||||
It's comparable to [`android_native_app_glue.c`][ndk_concepts]
|
||||
for C/C++ applications.
|
||||
|
||||
`android-activity` supports [`NativeActivity`] or [`GameActivity`] from the
|
||||
Android Game Development Kit and can be extended to support additional base
|
||||
classes.
|
||||
|
||||
`android-activity` provides a way to load a `cdylib` via the `onCreate` method of
|
||||
your `Activity` class; run an `android_main()` function in a separate thread from the Java
|
||||
main thread and marshal events (such as lifecycle events and input events) between
|
||||
Java and your native thread.
|
||||
|
||||
[`Activity`]: https://developer.android.com/reference/android/app/Activity
|
||||
[`NativeActivity`]: https://developer.android.com/reference/android/app/NativeActivity
|
||||
[ndk_concepts]: https://developer.android.com/ndk/guides/concepts#naa
|
||||
[`GameActivity`]: https://developer.android.com/games/agdk/integrate-game-activity
|
||||
|
||||
### Example
|
||||
|
||||
@@ -20,7 +30,7 @@ Cargo.toml
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
android_logger = "0.11"
|
||||
native-activity = { git = "https://github.com/rib/agdk-rust/" }
|
||||
android-activity = { git = "https://github.com/rib/android-activity/", features = [ "native-activity" ] }
|
||||
|
||||
[lib]
|
||||
crate_type = ["cdylib"]
|
||||
@@ -29,15 +39,14 @@ crate_type = ["cdylib"]
|
||||
lib.rs
|
||||
```rust
|
||||
use log::info;
|
||||
use native_activity::{PollEvent, MainEvent};
|
||||
use android_activity::{PollEvent, MainEvent};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn android_main() {
|
||||
fn android_main(app: AndroidApp) {
|
||||
android_logger::init_once(
|
||||
android_logger::Config::default().with_min_level(log::Level::Info)
|
||||
);
|
||||
|
||||
let app = native_activity::android_app();
|
||||
loop {
|
||||
app.poll_events(Some(std::time::Duration::from_millis(500)) /* timeout */, |event| {
|
||||
match event {
|
||||
@@ -71,8 +80,8 @@ adb logcat example:V *:S
|
||||
# Game Activity
|
||||
|
||||
Originally the aim was to enable support for building Rust applications based on the
|
||||
[GameActivity] based class provided by [Google's Android Game Development Kit][agdk]
|
||||
which should also facilitate integration with additional AGDK libraries including:
|
||||
[GameActivity] class provided by [Google's Android Game Development Kit][agdk]
|
||||
which can also facilitate integration with additional AGDK libraries including:
|
||||
1. [Game Text Input](https://developer.android.com/games/agdk/add-support-for-text-input): a library
|
||||
to help fullscreen native applications utilize the Android soft keyboard.
|
||||
2. [Game Controller Library, aka 'Paddleboat'](https://developer.android.com/games/sdk/game-controller):
|
||||
@@ -98,7 +107,7 @@ This project also supports [`NativeActivity`][NativeActivity] based applications
|
||||
NativeActivity is more limited than `GameActivity` and does not derive from `AppCompatActivity` it
|
||||
can sometimes still be convenient to build on `NativeActivity` in situations where you are using a
|
||||
limited/minimal build system that is not able to compile Java or Kotlin code or fetch from Maven
|
||||
repositories. This is because `NativeActivity` is included as part of the Android platform.
|
||||
repositories - this is because `NativeActivity` is included as part of the Android platform.
|
||||
|
||||
[NativeActivity]: https://developer.android.com/reference/android/app/NativeActivity
|
||||
|
||||
@@ -106,18 +115,12 @@ repositories. This is because `NativeActivity` is included as part of the Androi
|
||||
|
||||
## Compatibility
|
||||
|
||||
Both the [game-activity] glue crate and the [native-activity] glue crate support a common API that allows
|
||||
them to be used interchangably, depending on which base class your application decides to use.
|
||||
All `Activity` classes are supported via a common API that enables you to write
|
||||
`Activity` subclass agnostic code wherever you don't depend on features that are
|
||||
specific to a particular subclass.
|
||||
|
||||
Although it's expected that the `game-activity` crate will gain features that aren't possible with `native-activity`
|
||||
those should be covered by optional features that allow downstream crates, such as Winit to practically be
|
||||
able to support alternative glue layers.
|
||||
|
||||
The hope is that the core, common API can be supported via any Activity subclass that your
|
||||
application needs to use.
|
||||
|
||||
[game-activity]: https://github.com/rib/agdk-rust/tree/main/game-activity
|
||||
[native-activity]: https://github.com/rib/agdk-rust/tree/main/native-activity
|
||||
For example, it makes it possible to have a [Winit backend](https://github.com/rib/winit/tree/agdk-game-activity)
|
||||
that supports Android applications running with different `Activity` classes.
|
||||
|
||||
## API Summary
|
||||
|
||||
@@ -126,48 +129,45 @@ application needs to use.
|
||||
The glue crates define a standard entrypoint ABI for your `cdylib` that looks like:
|
||||
|
||||
```rust
|
||||
use android_activity::AndroidApp;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn android_main() {
|
||||
fn android_main(app: AndroidApp) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
There's currently no high-level macro provided for things like initializing logging or allowing the
|
||||
main function to return a `Result<>` since it's expected that different downstream frameworks may
|
||||
each have differing oppinions on the details and may want to provide their own macros.
|
||||
There's currently no high-level macro provided for things like initializing
|
||||
logging or allowing the main function to return a `Result<>` since it's expected
|
||||
that different downstream frameworks may each have differing opinions on the
|
||||
details and may want to provide their own macros.
|
||||
|
||||
### Global `AndroidApp`
|
||||
|
||||
The glue layer provides a `'static` `AndroidApp` API to access state about your running application
|
||||
and handle synchronized interaction between your native Rust application and the `Activity` running
|
||||
on the Java main thread.
|
||||
### `AndroidApp`
|
||||
|
||||
Your `android_main()` function is passed an `AndroidApp` struct to access state
|
||||
about your running application and handle synchronized interaction between your
|
||||
native Rust application and the `Activity` running on the Java main thread.
|
||||
|
||||
For example, the `AndroidApp` API enables:
|
||||
1. Access to Android lifecycle events
|
||||
2. Notifications of SurfaceView lifecycle events
|
||||
3. Access to input events
|
||||
4. Ability to save and restore state each time your process stops and starts
|
||||
5. Access application [`Configuration`] state
|
||||
6. internal/external/obb filesystem paths
|
||||
|
||||
For example:
|
||||
```rust
|
||||
#[no_mangle]
|
||||
extern "C" fn android_main() {
|
||||
let app = game_activity::android_app();
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
_Note: that some of the `AndroidApp` APIs (such as for polling events) are only deemed safe to use
|
||||
from the application's main thread_
|
||||
_Note: that some of the `AndroidApp` APIs (such as for polling events) are only
|
||||
deemed safe to use from the application's main thread_
|
||||
|
||||
[`Configuration`]: https://developer.android.com/reference/android/content/res/Configuration
|
||||
|
||||
### Synchronized event callbacks
|
||||
|
||||
The `AndroidApp::poll_events()` API is similar to the Winit `EventLoop::run` API in that it
|
||||
takes a `FnMut` closure that is called for each outstanding event (such as for lifecycle events).
|
||||
This is modeled on the original `android_native_app_glue` design for C/C++ that reserves the
|
||||
ability for the glue layer to insert "pre-" and "-post" hooks around the application's event
|
||||
callback that can handle any required synchronization with the Java main thread.
|
||||
This design ensures the glue layer can transparently handle any required synchronization with
|
||||
Java before and after each callback.
|
||||
|
||||
For example, when the Java main thread notifies the glue layer that its `SurfaceView` is being
|
||||
destroyed the Java thread will then block until it gets an explicit acknowledgement that the
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
This crate provides a "glue" layer for building native Rust applications on Android, supporting multiple `Activity` base classes that the application can choose.
|
||||
|
||||
Currently the crate supports `NativeActivity` or [`GameActivity`](https://developer.android.com/games/agdk/integrate-game-activity) from the Android Game Development Kit.
|
||||
|
||||
This serves a similar purpose to [`android_native_app_glue.c`](https://android.googlesource.com/platform/development/+/4948c163663ecc343c97e4c2a2139234f1d3273f/ndk/sources/android/native_app_glue) for `C/C++` applications.
|
||||
|
||||
Here's a minimal illustration of an Android main function and main loop based on this crate:
|
||||
|
||||
```rust
|
||||
use log::info;
|
||||
use android_activity::{AndroidApp, PollEvent, MainEvent};
|
||||
|
||||
#[no_mangle]
|
||||
fn android_main(app: AndroidApp) {
|
||||
android_logger::init_once(
|
||||
android_logger::Config::default().with_min_level(log::Level::Info)
|
||||
);
|
||||
|
||||
loop {
|
||||
app.poll_events(Some(std::time::Duration::from_millis(500)) /* timeout */, |event| {
|
||||
match event {
|
||||
PollEvent::Wake => { info!("Early wake up"); },
|
||||
PollEvent::Timeout => { info!("Timed out"); },
|
||||
PollEvent::Main(main_event) => {
|
||||
info!("Main event: {:?}", main_event);
|
||||
match main_event {
|
||||
MainEvent::Destroy => { return; }
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
app.input_events(|event| {
|
||||
info!("Input Event: {event:?}");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,21 +1,17 @@
|
||||
This tests using the game_activity crate with egui, winit and wgpu.
|
||||
This tests using `GameActivity` with egui, winit and wgpu.
|
||||
|
||||
This is based on a re-worked winit backend here:
|
||||
https://github.com/rib/winit/tree/agdk-game-activity
|
||||
|
||||
and based on updated egui-winit and egui-wgpu crates here:
|
||||
https://github.com/rib/egui/tree/android-deferred-winit-wgpu
|
||||
https://github.com/rib/winit/tree/android-activity
|
||||
|
||||
```
|
||||
rustup target add aarch64-linux-android
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-ndk
|
||||
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
|
||||
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
./gradlew build
|
||||
./gradlew installDebug
|
||||
adb shell am start -n co.realfit.agdkegui/.MainActivity
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
This is a minimal test application that just runs a mainloop based
|
||||
on game_activity::poll_events() and traces the events received
|
||||
without doing any rendering. It also saves and restores some
|
||||
minimal application state.
|
||||
|
||||
This is a minimal test application based on `GameActivity` that just
|
||||
runs a mainloop based on android_activity::poll_events() and traces
|
||||
the events received without doing any rendering. It also saves and
|
||||
restores some minimal application state.
|
||||
|
||||
```
|
||||
rustup target add aarch64-linux-android
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-ndk
|
||||
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
|
||||
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
./gradlew build
|
||||
./gradlew installDebug
|
||||
adb shell am start -n co.realfit.agdkmainloop/.MainActivity
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
This tests using the game_activity crate with winit and wgpu.
|
||||
This tests using `GameActivity` with winit and wgpu.
|
||||
|
||||
This is based on a re-worked winit backend here:
|
||||
https://github.com/rib/winit/tree/agdk-game-activity
|
||||
https://github.com/rib/winit/tree/android-activity
|
||||
|
||||
Although it would have been possible to handle the suspend/resume
|
||||
lifecycle events with a simpler approach of destroying and
|
||||
@@ -16,14 +16,13 @@ applications (that need to be portable) can work. (enable
|
||||
"desktop" feature to build binary)
|
||||
|
||||
```
|
||||
rustup target add aarch64-linux-android
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-ndk
|
||||
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
|
||||
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
./gradlew build
|
||||
./gradlew installDebug
|
||||
adb shell am start -n co.realfit.agdkwinitwgpu/.MainActivity
|
||||
|
||||
@@ -1,31 +1,22 @@
|
||||
This is a minimal test application similar to `agdk-mainloop` that
|
||||
is based on `NativeActivity` instead of `GameActivity`.
|
||||
|
||||
It shows how to run a mainloop based on `native_activity::poll_events()` and
|
||||
traces the events received without doing any rendering. It also saves and
|
||||
This is a minimal test application based on `NativeActivity` that just
|
||||
runs a mainloop based on android_activity::poll_events() and traces
|
||||
the events received without doing any rendering. It also saves and
|
||||
restores some minimal application state.
|
||||
|
||||
Since this test doesn't require a custom `Activity` subclass it's
|
||||
optionally possible to build this example with `cargo apk`.
|
||||
|
||||
The idea here is to test whether we can have a `NativeActivity` based
|
||||
glue layer which is API compatible with `game-activity`, which can
|
||||
optionally be used for _very_ basic tests/demos that want the convenience
|
||||
of not needing to compile any Java code.
|
||||
|
||||
# Gradle Build
|
||||
```
|
||||
rustup target add aarch64-linux-android
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-ndk
|
||||
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
|
||||
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
./gradlew build
|
||||
./gradlew installDebug
|
||||
adb shell am start -n co.realfit.namainloop/.MainActivity
|
||||
```
|
||||
|
||||
# Cargo APK Build
|
||||
@@ -33,7 +24,9 @@ adb shell am start -n co.realfit.namainloop/.MainActivity
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_SDK_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-apk
|
||||
|
||||
cargo apk build
|
||||
cargo apk run
|
||||
```
|
||||
```
|
||||
|
||||
@@ -7,14 +7,13 @@ Note: unlike the `na-mainloop` example, this one can't be built via
|
||||
|
||||
# Gradle Build
|
||||
```
|
||||
rustup target add aarch64-linux-android
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
cargo install cargo-ndk
|
||||
|
||||
export ANDROID_NDK_HOME="path/to/ndk"
|
||||
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
|
||||
|
||||
export ANDROID_HOME="path/to/sdk"
|
||||
./gradlew build
|
||||
./gradlew installDebug
|
||||
adb shell am start -n co.realfit.nasubclassjni/.MainActivity
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
This is the same as agdk-winit-wgpu except it enables the "native-activity"
|
||||
feature for winit, for running with `NativeActivity` instead of `GameActivity`
|
||||
|
||||
This is to see if it's practical to support multiple glue implementations with
|
||||
a common API.
|
||||
This is the same as agdk-winit-wgpu except it runs with `NativeActivity`
|
||||
instead of `GameActivity`
|
||||
|
||||
# Gradle Build
|
||||
```
|
||||
@@ -23,7 +20,7 @@ export ANDROID_NDK_HOME="path/to/ndk"
|
||||
export ANDROID_SDK_HOME="path/to/sdk"
|
||||
|
||||
rustup target add aarch64-linux-android
|
||||
|
||||
cargo install cargo-apk
|
||||
|
||||
cargo apk run
|
||||
```
|
||||
Reference in New Issue
Block a user