Crate android_activity
source ·Expand description
A glue layer for building standalone, Rust applications on Android
This crate 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
for C/C++ applications.
Currently the crate supports two Activity
base classes:
NativeActivity
- Built in to Android, this doesn’t require compiling any Java or Kotlin code.GameActivity
- From the Android Game Development Kit, it has more sophisticated input handling support thanNativeActivity
.GameActivity
is also based on theAndroidAppCompat
class which can help with supporting a wider range of devices.
Standalone applications based on this crate need to be built as cdylib
libraries, like:
[lib]
crate_type=["cdylib"]
and implement a #[no_mangle]
android_main
entry point like this:
#[no_mangle]
fn android_main(app: AndroidApp) {
}
Once your application’s Activity
class has loaded and it calls onCreate
then
android-activity
will spawn a dedicated thread to run your android_main
function,
separate from the Java thread that created the corresponding Activity
.
AndroidApp
provides an interface to query state for the application as
well as monitor events, such as lifecycle and input events, that are
marshalled between the Java thread that owns the Activity
and the native
thread that runs the android_main()
code.
§Cheaply Clonable AndroidApp
AndroidApp
is intended to be something that can be cheaply passed around
by referenced within an application. It is reference counted and can be
cheaply cloned.
§Send
and Sync
AndroidApp
Although an AndroidApp
implements Send
and Sync
you do need to take
into consideration that some APIs, such as AndroidApp::poll_events()
are
explicitly documented to only be usable from your android_main()
thread.
§Main Thread Initialization
Before android_main()
is called, the following application state
is also initialized:
- An I/O thread is spawned that will handle redirecting standard input
and output to the Android log, visible via
logcat
. - A
JavaVM
andActivity
instance will be associated with thendk_context
crate so that other, independent, Rust crates are able to find a JavaVM for making JNI calls. - The
JavaVM
will be attached to the native thread - A Looper is attached to the Rust native thread.
These are undone after android_main()
returns
§Android Extensible Enums
There are numerous enums in the android-activity
API which are effectively
bindings to enums declared in the Android SDK which need to be considered
runtime extensible.
Any enum variants that come from the Android SDK may be extended in future versions of Android and your code could be exposed to new variants if you build an application that might be installed on new versions of Android.
This crate follows a convention of adding a hidden __Unknown(u32)
variant
to these enum to ensure we can always do lossless conversions between the
integers from the SDK and our corresponding Rust enums. This can be
important in case you need to pass certain variants back to the SDK
regardless of whether you knew about that variants specific semantics at
compile time.
You should never include this __Unknown(u32)
variant within any exhaustive
pattern match and should instead treat the enums like #[non_exhaustive]
enums that require you to add a catch-all for any unknown => {}
values.
Any code that would exhaustively include the __Unknown(u32)
variant when
pattern matching can not be guaranteed to be forwards compatible with new
releases of android-activity
which may add new Rust variants to these
enums without requiring a breaking semver bump.
You can (infallibly) convert these enums to and from primitive u32
values
using .into()
:
For example, here is how you could ensure forwards compatibility with both
compile-time and runtime extensions of a SomeEnum
enum:
match some_enum {
SomeEnum::Foo => {},
SomeEnum::Bar => {},
unhandled => {
let sdk_val: u32 = unhandled.into();
println!("Unhandled enum variant {some_enum:?} has SDK value: {sdk_val}");
}
}
Modules§
Structs§
- The top-level state and interface for a native Rust application
- A means to wake up the main thread while it is blocked waiting for I/O
- A (cheaply clonable) reference to this application’s
ndk::configuration::Configuration
- A rectangle with integer edge coordinates. Used to represent window insets, for example.
- An interface for loading application state during MainEvent::Resume events
- An interface for saving application state during MainEvent::SaveState events
- Flags for
AndroidApp::set_window_flags
as per the android.view.WindowManager.LayoutParams Java API
Enums§
- Indicates whether an application has handled or ignored an event
- An application event delivered during
AndroidApp::poll_events
- An event delivered during
AndroidApp::poll_events