Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 aarch64-linux-android -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
39 changes: 19 additions & 20 deletions docs-template/EXAMPLE_README.md.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ 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)
- [iOS](#ios)
- [Setup](#setup-1)
- [Build & Run](#build--run-1)
Expand Down Expand Up @@ -88,6 +88,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,16 +107,20 @@ Alternatively, you can install Android Studio.

#### Build & Run

**⚠️ Note:** For running the example on `x86_64`, the `--release` flag is currently required.

**⚠️ Note:** The `-P 26` flag is currently required for building the example. If not included, you might get the error: `unable to find library -laaudio`.

To build an Android app, you first need to build shared object files for the target architecture with `cargo-ndk`:

```sh
cargo ndk -t <target_name> -P 26 -o <project_name>/app/src/main/jniLibs build
cargo ndk build -t <target_name> -P 26 -o <project_path>/app/src/main/jniLibs
```

For example, to compile to a 64-bit ARM platform:

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

Setting the output path ensures the shared object files can be found in target-specific directories under `jniLibs` where the JNI can find them.
Expand All @@ -122,6 +130,7 @@ See the `cargo-ndk` [README](https://crates.io/crates/cargo-ndk) for other optio
After this you can build it with `gradlew`:

```sh
cd ./android
./gradlew build
```

Expand All @@ -147,29 +156,23 @@ 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`.
**⚠️ 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 36 as `targetSdk` to be able to benefit from security and performance improvements. For backwards compatibility, the example specifies Android API 31 as `minSdk`. This approach is recommended in the [Android Developers documentation](https://developer.android.com/google/play/requirements/target-sdk#why-target).

Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo).
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 31 and higher, so if you want to use an older API, you need to switch to [`NativeActivity`](https://developer.android.com/reference/android/app/NativeActivity).

To use `NativeActivity`, you need to edit it in `cargo.toml` manually like this:
To use `NativeActivity`, you need to write a custom `MainActivity.kt` using `NativeActivity` instead of `GameActivity` and add the `android-native-activity` feature to Bevy in your `Cargo.toml` like this:

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

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

##### About `cargo-apk`

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 Down Expand Up @@ -209,10 +212,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
39 changes: 19 additions & 20 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ 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)
- [iOS](#ios)
- [Setup](#setup-1)
- [Build & Run](#build--run-1)
Expand Down Expand Up @@ -688,6 +688,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 @@ -703,16 +707,20 @@ Alternatively, you can install Android Studio.

#### Build & Run

**⚠️ Note:** For running the example on `x86_64`, the `--release` flag is currently required.

**⚠️ Note:** The `-P 26` flag is currently required for building the example. If not included, you might get the error: `unable to find library -laaudio`.

To build an Android app, you first need to build shared object files for the target architecture with `cargo-ndk`:

```sh
cargo ndk -t <target_name> -P 26 -o <project_name>/app/src/main/jniLibs build
cargo ndk build -t <target_name> -P 26 -o <project_path>/app/src/main/jniLibs
```

For example, to compile to a 64-bit ARM platform:

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

Setting the output path ensures the shared object files can be found in target-specific directories under `jniLibs` where the JNI can find them.
Expand All @@ -722,6 +730,7 @@ See the `cargo-ndk` [README](https://crates.io/crates/cargo-ndk) for other optio
After this you can build it with `gradlew`:

```sh
cd ./android
./gradlew build
```

Expand All @@ -747,29 +756,23 @@ 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`.
**⚠️ 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 36 as `targetSdk` to be able to benefit from security and performance improvements. For backwards compatibility, the example specifies Android API 31 as `minSdk`. This approach is recommended in the [Android Developers documentation](https://developer.android.com/google/play/requirements/target-sdk#why-target).

Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo).
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 31 and higher, so if you want to use an older API, you need to switch to [`NativeActivity`](https://developer.android.com/reference/android/app/NativeActivity).

To use `NativeActivity`, you need to edit it in `cargo.toml` manually like this:
To use `NativeActivity`, you need to write a custom `MainActivity.kt` using `NativeActivity` instead of `GameActivity` and add the `android-native-activity` feature to Bevy in your `Cargo.toml` like this:

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

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

##### About `cargo-apk`

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 Down Expand Up @@ -809,10 +812,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
12 changes: 12 additions & 0 deletions examples/mobile/android/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf

# These are Windows script files and should use crlf
*.bat text eol=crlf

# Binary files should be left untouched
*.jar binary

65 changes: 65 additions & 0 deletions examples/mobile/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
plugins {
alias(libs.plugins.android.application)
}

kotlin {
compilerOptions {
languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3
jvmToolchain(8)
}
}

android {
namespace = "org.bevyengine.example"
compileSdk = 36

// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/DefaultConfig
defaultConfig {
applicationId = "org.bevyengine.example"
minSdk = 31
targetSdk = 36
// NOTE: Increase by 1 on each release
versionCode = 1
// NOTE: Update with full semantic version on each release
versionName = "0.0.0"
// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/Ndk
ndk {
abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a", "x86_64"))
}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/BuildType
buildTypes {
getByName("release") {
// https://developer.android.com/topic/performance/app-optimization/enable-app-optimization
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
}
}
// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/CompileOptions
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/BuildFeatures
buildFeatures {
prefab = true
}
// https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/dsl/AndroidSourceSet
sourceSets {
getByName("main") {
assets {
directories += "../../../../assets"
}
}
}
}

dependencies {
implementation(libs.appcompat)
implementation(libs.core)
implementation(libs.material)
implementation(libs.games.activity)
implementation(libs.core.ktx)
}
15 changes: 15 additions & 0 deletions examples/mobile/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application android:icon="@mipmap/ic_launcher" android:label="Bevy Example" android:roundIcon="@mipmap/ic_launcher" android:theme="@style/Theme.AppCompat.NoActionBar" tools:targetApi="36">
<activity android:name=".MainActivity" android:exported="true" android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode" android:theme="@style/Theme.AppCompat.NoActionBar">
<meta-data android:name="android.app.lib_name" android:value="bevy_mobile_example" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.bevyengine.example

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() {
/**
* Hide system UI if the app window is focused.
*
*
* Called when the current Window of the activity gains or loses focus.
*/
override fun onWindowFocusChanged(hasFocus: Boolean) {
// Call parent class implementation of onWindowFocusChanged to make sure that we are updating correctly.
super.onWindowFocusChanged(hasFocus)

if (hasFocus) {
hideSystemUi()
}
}

/**
* Hide system UI.
*/
private fun hideSystemUi() {
val windowInsetsController =
WindowCompat.getInsetsController(window, window.decorView)

// Show bars if swiping
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// Hide both the status bar and the navigation bar.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
}

companion object {
// Load rust library
init {
System.loadLibrary("bevy_mobile_example")
}
}
}
12 changes: 12 additions & 0 deletions examples/mobile/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# https://docs.gradle.org/current/userguide/build_environment.html
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8

# This should be enabled by default, but for older gradle versions this is still necessary.
# See: https://developer.android.com/build/releases/agp-9-0-0-release-notes
android.useAndroidX=true

# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
12 changes: 12 additions & 0 deletions examples/mobile/android/gradle/gradle-daemon-jvm.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73c462e34475aeb6509ab7ba3eda218f/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/9e87f9444e29ce8efb3f66e8435d94b4/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73c462e34475aeb6509ab7ba3eda218f/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9e87f9444e29ce8efb3f66e8435d94b4/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1050b2216f8beaaecc1289b17d30b586/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/2208feeb3d4e12f412e9a450db1a842a/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/40b4344c056b4284246d176d9701577f/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9e87f9444e29ce8efb3f66e8435d94b4/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a86b70d151aa8c1a054e80f417232fa2/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/69a793dd932268c7d1ae9d8b855de8ed/redirect
toolchainVersion=17
Loading