This updates both the examples to Gradle 9 and AGP 9.1
The examples are identical, except that `na-mainloop` is based on
NativeActivity and the `agdk-mainloop` based on GameActivity.
The examples demonstrate:
- Using the `jni` API to define enough bindings to be able to send a Toast
- Using an `android_on_create` entry point for logging initialization
and JNI initialization
- Using `AndroidApp::run_on_java_main_thread()` to send a toast from the
Java main / UI thread
- Running an `android_main` event loop, including printing historic
pointer samples (a new 0.6.1 feature)
The examples support two input actions:
- Lifting your finger in the top-left corner of the screen will show the
onscreen keyboard
- Lifting your finger in the top-right corner of the screen will hide
the onscreen keyboard
If you edit and disable `configChanges` in `AndroidManifest.xml` then
these examples can also demonstrate that `android-activity` gracefully
handles repeated `Activity` create -> run -> destroy cycles.
The next breaking `ndk` release puts a lot of emphasis in improving
`enum`s to finally be marked `non_exhaustive`, and carry possible future
values in `__Unknown(i32)` variants. This removes the lossy conversions
that previously required `android-activity` to redefine its types, which
could all be removed again.
The `repr()` types have also been updated, as `enum` constants in C are
translated to `u32` by default in `bindgen` even though they're commonly
passed as `int` to every API function that consumes them.
With the way events are delivered via an `InputQueue` with
`NativeActivity` there is no direct access to the underlying KeyEvent
and MotionEvent Java objects and no `ndk` API that supports the
equivalent of `KeyEvent.getUnicodeChar()`
What `getUnicodeChar` does under the hood though is to do lookups into a
`KeyCharacterMap` for the corresponding `InputDevice` based on the
event's `key_code` and `meta_state` - which are things we can do via
some JNI bindings for `KeyCharacterMap`.
Although it's still awkward to expose an API like
`key_event.get_unicode_char()` we can instead provide an API that
lets you look up a `KeyCharacterMap` for any `device_id` and
applications can then use that for character mapping.
This approach is also more general than the `getUnicodeChar` utility
since it exposes other useful state, such as being able to check what
kind of keyboard input events are coming from (such as a full physical
keyboard vs a virtual / 'predictive' keyboard)
For consistency this exposes the same API through the game-activity
backend, even though the game-activity backend is technically able to
support unicode lookups via `getUnicodeChar` (since it has access to the
Java `KeyEvent` object).
This highlighted a need to be able to use other `AndroidApp` APIs while
processing input, which wasn't possible with the `.input_events()` API
design because the `AndroidApp` held a lock over the backend while
iterating events.
This changes `input_events()` to `input_events_iter()` which now returns
a form of lending iterator and instead of taking a callback that gets
called repeatedly by `input_events()` a similar callback is now passed
to `iter.next(callback)`.
The API isn't as ergonomic as I would have liked, considering that
lending iterators aren't a standard feature for Rust yet but also since
we still want to have the handling for each individual event go via a
callback that can report whether an event was "handled". I think the
slightly awkward ergonomics are acceptable though considering that
the API will generally be used as an implementation detail within
middleware frameworks like Winit.
Since this is the first example where we're creating non-trivial Java
bindings for an Android SDK API this adds some JNI utilities and
establishes a pattern for how we can implement a class binding.
It's an implementation detail but with how I wrote the binding I tried
to keep in mind the possibility of creating a procmacro later that would
generate some of the JNI boilerplate involved.
When splitting out the rust-android-examples we kept the agdk-mainloop
and na-mainloop examples in part so we would have some simple code we
can build as integration tests.
Since it's less likely that these will be referenced directly as
examples now, compared to those in rust-android-examples this removes
the lock files so we will instead always build against the latest semver
compatible dependencies.
Considering the simplicity of these examples, and minimal dependencies
these lock files probably weren't that worthwhile before either.
Most of the examples weren't strictly just demonstrating how to use the
android-activity API - rather they demonstrated using other libraries
in conjunction with android-activity.
Most of the examples have now been split into a standalone repository
under: https://github.com/rust-mobile/rust-android-examples
The na-mainloop and agdk-mainloop examples have been kept here since
they can be built against the local/in-tree version of android-activity
and are useful to keep for CI purposes.
This also runs `cargo update` for the na-mainloop and agdk-mainloop.
This updates the *-winit-wgpu examples to use `log::info!` instead of `trace!`
and sets the log level to `Info`
The examples now also print info about and Winit Window events.
This makes them more practical to use to see how Winit events
are delivered without lots of tracing spam from dependency crates.
- Updates deps
- Some README updates considering the Winit backend based on
android-activity has been merged upstream
- runs cargo fmt over examples
- Top-level Cargo.toml simply excludes "examples" instead of
listing each sub-directory separately
This example shows how to draw a triangle with GL[ES via the Glutin
crate (the app works on desktop and Android) and on Android it
demonstrates how to re-create the applications surface state when
it is paused and resumed.
The Renderer code and some utilities are from the upstream Glutin example.
The winit based examples no longer have an explicit dependency on
android-activity and they instead consume the `android-activity` API via
the Winit crate so there's no need to keep the versions synchronized.
The callback given to `AndroidApp::input_events()` is now expected to return
`InputStatus::Handled` or `InputStatus::Unhandled`.
When running with NativeActivity then if we know an input event hasn't been
handled we can notify the InputQueue which may result in fallback
handling.
Although the status is currently ignored with the GameActivity backend.
Since this is a breaking change that also affects the current Winit
backend this updates the winit based examples to stick with the 0.3
release of android-activity for now.
Fixes: #31
The latest branches for Winit (which update the Android backend to
use android-activity) now depend on the android-activity 0.2
release which broke the patching assumption for the Winit examples.
(they were patching based on the git url not crates.io)
It was also noticed that the latest android-activity-0.27 branch
isn't compatible with Egui currently because the (badly named) branch
is based on Winit master and there was recently a breaking API change
adding new window events which breaks Egui.
A note about the badly name branches has been added to the Cargo.toml
files for the Winit examples (they can't currently be fixes since
the -0.27 branch is part of a pull request).
For reference here:
- "android-activity" is based on Winit 0.27 (required for Egui compatibility)
- "android-activity-0.27" is based on Winit master
This patch adds Cargo.lock files for the Winit examples.
Fixes: #22
* Since we can rely on `Resumed` events for all platforms with Winit 0.27
we can remove the alternative `NewEvents` path for initializing state.
* Removes some unnecessary abstraction for the app state.
* Bumps agdk-egui to egui 0.19 (Winit 0.27)
This provides an API to access `Configuration` state for the application
without having to make deep copies of the large `Configuration` struct.
This should avoid the need for Winit to create a global static copy of
the Configuration whenever it changes - and instead it can just get
a `ConfigurationRef` which will always reflect the latest config for
the application.
Fixes: #5
In Winit then we ideally want to be able to associate a cloned reference to
the AndroidApp with the `Window` and `MonitorHandle` types (since that's the
most practical way to access the native_window and config state for the
application) but for that `AndroidApp` needs to be Send + Sync
I was mistaken recently, thinking that cpal's dev-dependency on ndk-glue
was somehow being inherited by the example. Actually the real issue was
that cpal 0.13.5 has a regular _dependency_ on ndk-glue, which is a much
simpler explanation for why we were seeing a crash.
This updates the example to just use the master branch of cpal, which we'll
need until there is a new release of cpal.
This makes a small change to the C glue code for GameActivity to send
looper wake ups when new input is received (only sending a single wake
up, until the application next handles input).
When a wake up is received and we recognise that new input is available
then an `InputAvailable` event is sent to the application - consistent
with how NativeActivity can deliver `InputAvailable` events.
This addresses a significant feature disparity between GameActivity and
NativeActivity that meant GameActivity was not practically usable for
GUI applications that wouldn't want to render continuously like a game.
Addresses #4
Based on the android example that's in the cpal repo, this test plays
a 440hz sine wave and is based on GameActivity
Note: this requires a workaround branch for cpal that comments out
a dev-dependency on ndk-glue that cpal has for its android example.
This is needed because Cargo is spuriously propagating this dev
dependency outside of the cpal package (which leads to a crash)
This fixes build errors about not specifying either of the
"native-activity" or "game-activity" features.
The issue came about because the in-tree examples want to
build against the in-tree version of android-activity located
with a relative `path = ` but these particular examples
depend on Winit which would resolve a second implementation
of android-activity, via a github url - where Cargo will treat
them as completely different crates.
"native-activity" builds were recently broken by bb8eeb705c which
this patch fixes.
The na-mainloop example has also been updated to verify this by
reducing the fake "render" timeout and also triggering a fake
render when an InputAvailable event is received.
Fixes: #12