Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e6d7c8a
examples: Use single up-to-date android example
leomeinel Mar 24, 2026
eb2f806
fix: Fix README.md
leomeinel Mar 24, 2026
a18625a
fix: Readd -P 26 flag to cargo ndk
leomeinel Mar 25, 2026
09e50c0
readability: Readd/Reposition mobile example tables
leomeinel Mar 25, 2026
1abf541
fixup: Omit unnecessary chmod in build
leomeinel Mar 28, 2026
9901132
fixup: Remove leftover --link-libcxx-shared
leomeinel Mar 28, 2026
ef206c9
fixup: Remove FIXME for -P 26
leomeinel Mar 28, 2026
58a3741
fixup: Remove leftover --release flag
leomeinel Mar 28, 2026
91587af
fixup: Enable edge to edge onCreate
leomeinel Apr 8, 2026
60c9455
docs: Add detailed instructions on how to use NativeActivity
leomeinel Apr 8, 2026
a505e01
fix: Reword onCreate comment
leomeinel Apr 8, 2026
4a49d4e
fix: Consistently use in for steps
leomeinel Apr 8, 2026
49d6ff7
fixup: Use arm64-v8a and refine instructions
leomeinel Apr 12, 2026
0006569
fixup: Use toolchain/jdk version 17
leomeinel Apr 13, 2026
1ca45b0
fix: Fix diff and add supported os for gradlew
leomeinel Apr 13, 2026
5817282
fixup: Commit reword suggestions
leomeinel Apr 13, 2026
07a0a96
dependencies: Bump games-activity to 4.4.1
leomeinel Apr 13, 2026
d5d52a4
fixup: Explain -P 26
leomeinel Apr 13, 2026
3ae05c5
dependencies: Bump agp to 9.1.1
leomeinel Apr 13, 2026
e219111
fix: Use minSdk 26 and correct minSdk for GameActivity
leomeinel Apr 13, 2026
9152245
reword: Consistently use unnecessary dependencies
leomeinel Apr 13, 2026
e434b45
docs: Update libs.versions.toml used in diff
leomeinel Apr 13, 2026
a4a80fa
docs: Explain GameActivity vs NativeActivity in subsections
leomeinel Apr 13, 2026
7d7474a
chore(dependencies): Update android example dependencies
leomeinel Apr 28, 2026
4a1cb4d
docs: Update versions in NativeActivity diff
leomeinel Apr 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/validation-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ jobs:
run: cargo install --force cargo-ndk

- name: Build .so file
run: cargo ndk -t arm64-v8a -P 26 -o android_example/app/src/main/jniLibs build --package bevy_mobile_example
run: cargo ndk build -t arm64-v8a -P 26 -p bevy_mobile_example -o ./examples/mobile/android/app/src/main/jniLibs

- name: Build app for Android
run: cd examples/mobile/android_example && chmod +x gradlew && ./gradlew build
run: cd ./examples/mobile/android && ./gradlew build

run-examples-on-wasm:
if: ${{ github.event_name == 'merge_group' }}
Expand Down
214 changes: 173 additions & 41 deletions docs-template/EXAMPLE_README.md.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ git checkout v0.4.0
- [Android](#android)
- [Setup](#setup)
- [Build & Run](#build--run)
- [Debugging](#debugging)
- [Old phones](#old-phones)
- [About `cargo-apk`](#about-cargo-apk)
- [`GameActivity` vs `NativeActivity`](#gameactivity-vs-nativeactivity)
- [Migrating from `GameActivity` to `NativeActivity`](#migrating-from-gameactivity-to-nativeactivity)
- [iOS](#ios)
- [Setup](#setup-1)
- [Build & Run](#build--run-1)
Expand Down Expand Up @@ -88,6 +90,10 @@ Example | Description

### Android

Example | File | Description
--- | --- | ---
`mobile` | [`mobile/src/lib.rs`](./mobile/src/lib.rs) | A 3d Scene with a button and playing sound

#### Setup

```sh
Expand All @@ -103,31 +109,71 @@ Alternatively, you can install Android Studio.

#### Build & Run

To build an Android app, you first need to build shared object files for the target architecture with `cargo-ndk`:
**⚠️ Note:** In order to run this example on `x86_64`, you may need to use the `--release` flag.

```sh
cargo ndk -t <target_name> -P 26 -o <project_name>/app/src/main/jniLibs build
```
**⚠️ Note:** The `-P 26` flag is currently required for building the example. It sets the correct API level required by `bevy_audio`.

For example, to compile to a 64-bit ARM platform:
1. Build shared object files for the target architecture with `cargo-ndk`:

```sh
cargo ndk -t arm64-v8a -P 26 -o android_example/app/src/main/jniLibs build
```
```sh
cargo ndk build -t <target_name> -P 26 -o <project_path>/app/src/main/jniLibs
Comment thread
alice-i-cecile marked this conversation as resolved.
```

Setting the output path ensures the shared object files can be found in target-specific directories under `jniLibs` where the JNI can find them.
*Setting the output path ensures the shared object files can be found in target-specific directories under `jniLibs` where the JNI can find them. See the `cargo-ndk` [README](https://crates.io/crates/cargo-ndk) for additional options.*

See the `cargo-ndk` [README](https://crates.io/crates/cargo-ndk) for other options.
**Additional Info:**

After this you can build it with `gradlew`:
<details>
<summary>Example for arm64-v8a target_name</summary>

```sh
./gradlew build
```
Build for `arm64-v8a`/`aarch64-linux-android` via:

```sh
cargo ndk build -t arm64-v8a -P 26 -o ./android/app/src/main/jniLibs
```

</details>

<details>
<summary>Get target_name from adb</summary>

Print the required `target_name` for a device connected via `adb` via:

```sh
adb shell getprop ro.product.cpu.abi
```

</details>

2. Run Gradle via `./gradlew` (macOS, Linux, or BSD) or `gradlew.bat` (Windows) to install the app:

Install the app via:

```sh
cd ./android
./gradlew installDebug
```

*This step installs the app to a device connected via `adb`. Afterwards you can open the app on the device. You can also use Android Studio for this step.*

Or build it with Android Studio.
**Additional Info:**

Then you can test it in your Android project.
<details>
<summary>Additional Gradle tasks</summary>

Only build the app via:

```sh
./gradlew build
```

Print additional tasks via:

Comment thread
leomeinel marked this conversation as resolved.
```sh
./gradlew tasks
```

</details>

#### Debugging

Expand All @@ -147,29 +193,120 @@ adb uninstall org.bevyengine.example

#### Old phones

In its examples, Bevy targets the minimum Android API that Play Store <!-- markdown-link-check-disable -->
[requires](https://developer.android.com/distribute/best-practices/develop/target-sdk) to upload and update apps. <!-- markdown-link-check-enable -->
Users of older phones may want to use an older API when testing. By default, Bevy uses [`GameActivity`](https://developer.android.com/games/agdk/game-activity), which only works for Android API level 31 and higher, so if you want to use older API, you need to switch to `NativeActivity`.

Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo).

To use `NativeActivity`, you need to edit it in `cargo.toml` manually like this:

```toml
bevy = { version = "0.19", features = ["android-native-activity"] }
```

Then build it as the [Build & Run](#build--run) section stated above.

##### About `cargo-apk`
**⚠️ Note:** If you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo).

In its example, Bevy uses Android API 37 as `targetSdk` to be able to benefit from security and performance improvements. For backwards compatibility, the example specifies Android API 26 as `minSdk`. This approach is recommended in the [Android Developers documentation](https://developer.android.com/google/play/requirements/target-sdk#why-target).

If you want to support older APIs, you can set a lower `minSdk`. You should however make sure that dependencies in `android/gradle/libs.versions.toml` support your API. You might also have to migrate to `NativeActivity`.

##### [`GameActivity`](https://developer.android.com/games/agdk/game-activity) vs [`NativeActivity`](https://developer.android.com/reference/android/app/NativeActivity)

Bevy uses `GameActivity`, which only works for Android API 23 and higher.

Quoting from [Android Developers](https://developer.android.com/games/agdk/game-activity), the major differences are as follows:

> If you are already familiar with `NativeActivity`, the major differences between `GameActivity` and `NativeActivity` are as follows:
>
> - `GameActivity` renders into a [`SurfaceView`](https://developer.android.com/reference/android/view/SurfaceView), making it much easier for games to interact with other UI components.
> - For touch and key input events, `GameActivity` has a completely new implementation with the [`android_input_buffer`](https://developer.android.com/reference/games/game-activity/structandroid/input-buffer) interface, separate from the [`InputQueue`](https://developer.android.com/reference/android/view/InputQueue) that NativeActivity uses.
> - `GameActivity` is a derived class of `AppCompatActivity`, which lets you seamlessly use other Jetpack components. [`ActionBar`](https://developer.android.com/reference/android/app/ActionBar), [`Fragment`](https://developer.android.com/guide/fragments), and others are all available.
> - `GameActivity` adds text input functionality by integrating [`the GameTextInput library`](https://developer.android.com/games/agdk/add-support-for-text-input).
> - Apps derived from `GameActivity` are expected to build all three parts of C/C++ code into one library. On the other hand, `NativeActivity`'s JNI functions are a part of the framework (always loaded by OS). Hence, only the `native_app_glue` and application’s C/C++ code are expected to be built into one library.
> - `NativeActivity` is a part of Android framework and follows its release cycle (typically yearly). GameActivity is a part of the Jetpack library, which has a much more frequent release cycle (typically biweekly); new features and bug fixes can arrive much more quickly.
>
> **Note:** We strongly recommend using **GameActivity** for new games and other C/C++ intensive applications. If you have an existing **NativeActivity** application, we recommend migrating to **GameActivity**.

If you still want to use `NativeActivity`, please see the next section.

##### Migrating from `GameActivity` to `NativeActivity`

1. Replace `android-game-activity` feature with `android-native-activity` in `Cargo.toml`.
<details>
<summary>Required Changes (Example)</summary>

```diff
--- a/examples/mobile/Cargo.toml
+++ b/examples/mobile/Cargo.toml
[dependencies]
-bevy = { version = "0.19", features = ["android-game-activity"] }
+bevy = { version = "0.19", features = ["android-native-activity"] }
```

</details>
2. Remove unnecessary dependencies in `android/gradle/libs.versions.toml`.
<details>
<summary>Required Changes (Example)</summary>

```diff
--- a/examples/mobile/android/gradle/libs.versions.toml
+++ b/examples/mobile/android/gradle/libs.versions.toml
[versions]
agp = "9.2.0"
appcompat = "1.7.1"
core = "1.18.0"
-gamesActivity = "4.4.1" # Note: This must be compatible with `android-activity` crate used by bevy.
material = "1.13.0"
coreKtx = "1.18.0"

[libraries]
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
core = { group = "androidx.core", name = "core", version.ref = "core" }
-games-activity = { group = "androidx.games", name = "games-activity", version.ref = "gamesActivity" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
```

</details>
3. Remove unnecessary dependencies in `android/app/build.gradle.kts`.
<details>
<summary>Required Changes (Example)</summary>

```diff
--- a/examples/mobile/android/app/build.gradle.kts
+++ b/examples/mobile/android/app/build.gradle.kts
dependencies {
implementation(libs.appcompat)
implementation(libs.core)
implementation(libs.material)
- implementation(libs.games.activity)
implementation(libs.core.ktx)
}
```

</details>
4. Use `NativeActivity` in `MainActivity.kt`.
<details>
<summary>Required Changes (Example)</summary>

```diff
--- a/examples/mobile/android/app/src/main/kotlin/org/bevyengine/example/MainActivity.kt
+++ b/examples/mobile/android/app/src/main/kotlin/org/bevyengine/example/MainActivity.kt
package org.bevyengine.example

+import android.app.NativeActivity
import android.os.Bundle
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
-import com.google.androidgamesdk.GameActivity

/**
* Load rust library and handle android specifics to integrate with it.
*
*
* The library is loaded at class initialization and provided by jniLibs.
*/
-class MainActivity : GameActivity() {
+class MainActivity : NativeActivity() {
```

</details>

You can also build an APK with `cargo-apk`, a simpler and deprecated tool which doesn't support `GameActivity`. If you want to use this, there is a [folder](./mobile/android_basic) inside the mobile example with instructions.
### iOS

Example | File | Description
--- | --- | ---
`android` | [`mobile/src/lib.rs`](./mobile/src/lib.rs) | A 3d Scene with a button and playing sound

### iOS
`mobile` | [`mobile/src/lib.rs`](./mobile/src/lib.rs) | A 3d Scene with a button and playing sound

#### Setup

Expand All @@ -190,7 +327,6 @@ Using bash:
```sh
cd examples/mobile
make run
```

In an ideal world, this will boot up, install and run the app for the first
iOS simulator in your `xcrun simctl list devices`. If this fails, you can
Expand All @@ -209,10 +345,6 @@ open bevy_mobile_example.xcodeproj/
which will open xcode. You then must push the zoom zoom play button and wait
for the magic.

Example | File | Description
--- | --- | ---
`ios` | [`mobile/src/lib.rs`](./mobile/src/lib.rs) | A 3d Scene with a button and playing sound

### Wasm

#### Setup
Expand Down
Loading