Introduction

splash

What is Crossbow?

The crossbow project aims to provide a complete toolkit for cross-platform game development in Rust - from project creation to publishing. In addition, the project simplifies the creation, packaging, and signing of Android and iOS applications. We want to make most of our tools - engine agnostic to help rust game developers integrate them into their engines or games.

Why Crossbow?

There are already cargo-apk, cargo-mobile, cargo-xcode, etc. - why do I need another packaging tool?

Project crossbow is not only a packaging tool for Android and iOS - it's cross-platform build tools and toolkit for Rust! With crossbundle you can create native .apk/.aab without any Java or setup Gradle project with fancy Crossbow Android plugins (iOS in near future); with crossbundle-tools you can customize and create new commands; with crossbow-android you can write your own Android plugins in Java/Kotlin.

A lot of functionality was inspired by Godot, Xamarin, and cargo-apk.

Design Goals

  • Customizable: Create new commands with available tools.
  • Simple: Easy to install and start hacking but also pretty flexible for strong devs.
  • Capable: It's possible to build plain .apk/.aab or .app/.ipa; or with help of Gradle/XCode.
  • Rust: Don't leave your Rust code - everything can be configured from Cargo.toml.
  • Plugins: Godot-like plugins for Android (and iOS in future) with Rust wrapper!

Next steps

As the next steps we recommend you to install and setup crossbundle to be able to build, test, and run your project!

See Getting Started for more information.

Installation

Rust Setup

All crossbow crates are written in Rust. This means that before we begin, we need to set up our Rust development environment.

Installing Rust

Install Rust by following the Rust Getting Started Guide.

Once this is done, you should have the rustc compiler and the cargo build system installed in your path.

Rust Learning Resources

The goal of this book is to learn crossbow, so it won't serve as a full Rust education. If you would like to learn more about the Rust language, check out the following resources:

Crossbundle Setup

To begin with crossbow - you will need to install crossbundle first. You can do it simply by running the following command:

cargo install --git=https://github.com/dodorare/crossbow crossbundle

Next steps

To complete the installation of all requirements, read the documentation corresponding to your platform:

Android setup on Windows

Install necessary packages

  1. Use crossbundle install command or download and install Android Studio.
  2. Start Android Studio, and go through the Android Studio Setup Wizard with the Custom option and install the following (or install them in SDK Manager):
    • Android SDK
    • NDK (Side by side)
    • Android SDK Command-line Tools
    • Android SDK Build-Tools
    • Android SDK Platform-tools

Install necessary rustup targets

Run the following command:

rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android

Add environment variables

From the Start search bar, enter env and select Edit environment variables for your account.

Building strategyKeyValueDescription
Gradle project, native APK/AABANDROID_SDK_ROOT<path_to_sdk>\SdkCan be replaced with ANDROID_SDK_PATH and ANDROID_HOME. You might not install this env var if you used crossbundle install to set up required packages
or just want to build native APK or native AAB
Native APK/AABANDROID_NDK_ROOT<path_to_sdk>\Sdk\ndk<version>Can be replaced with ANDROID_NDK_PATH and NDK_HOME. You might not install this env var if you used crossbundle install to set up required packages
Gradle project, native APK/AABJAVA_HOME<path_to_jdk>\binAlso, we need to make sure we have a java runtime environment (JRE)
or Java developer kit (JDK) installed. We need jarsigner utility from there
Gradle projectGRADLE_HOME<path_to_gradle>Crossbow default build process requires installed Gradle on your PC. You can download it here
Native AABBUNDLETOOL_PATH<path_to_bundletool>Download bundletool from the GitHub repository or use crossbundle install

Or you can install required env via command line accordingly table above. Arguments were provided for example

SETX ANDROID_SDK_ROOT "C:\Users\Username\AppData\Local\Android\Sdk" /M
SETX ANDROID_NDK_ROOT "C:\Users\Username\AppData\Local\Android\Sdk\ndk\23.1.7779620" /M
SETX JAVA_HOME "C:\Program Files\Java\jdk-11.0.15+10" /M
SETX GRADLE_HOME "C:\Gradle\gradle-7.4.2" /M
SETX BUNDLETOOL_PATH "C:\Users\Username\bundletool-all-1.8.2.jar" /M

You have to close and reopen any existing console windows for these changes to take effect.

Set up your Android device

Follow the link to find out how to set up your device or android emulator

Next step

See hello-world to configure your project

After previous steps you can use crossbundle to build gradle project or native APK/AAB. Go to the links:

Setup Android Environment on Linux

Install necessary packages

  1. Use crossbundle install command or download and install Android Studio.
  2. Start Android Studio, and go through the Android Studio Setup Wizard with the Custom option and install the following (or install them in SDK Manager):
    • Android SDK
    • NDK (Side by side)
    • Android SDK Command-line Tools
    • Android SDK Build-Tools
    • Android SDK Platform-tools

Install necessary rustup targets

Run the following command:

rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android

Add environment variables

From the Start search bar, enter env and select Edit environment variables for your account.

Building strategyKeyValueDescription
Gradle project, native APK/AABANDROID_SDK_ROOT<path_to_sdk>\SdkCan be replaced with ANDROID_SDK_PATH and ANDROID_HOME. You might not install this env var if you used crossbundle install to set up required packages
or just want to build native APK or native AAB
Native APK/AABANDROID_NDK_ROOT<path_to_sdk>\Sdk\ndk<version>Can be replaced with ANDROID_NDK_PATH and NDK_HOME. You might not install this env var if you used crossbundle install to set up required packages
Gradle projectGRADLE_HOME<path_to_gradle>Crossbow default build process requires installed Gradle on your PC. You can download it here
Native AABBUNDLETOOL_PATH<path_to_bundletool>Download bundletool from the GitHub repository or use crossbundle install

For that edit ~/.bash_profile or ~/.bashrc files so they contain those lines:

export ANDROID_SDK_ROOT=$HOME/Android/Sdk
export ANDROID_NDK_ROOT=$HOME/Android/Sdk/ndk/23.1.7779620
export GRADLE_HOME=<path_to_gradle>
export BUNDLETOOL_PATH=<path_to_bundletool>

Also, we need to make sure we have a java runtime environment (JRE) installed. We need a key tool utility from there.
To make sure it's present type this command: ls /usr/lib/jvm/default/bin/ | grep keytool

But please be aware that your path may vary. The above path is for arch-based Linux.

If not, install JRE accordingly to your operating system: Examples:

  • Ubuntu: sudo apt install default-jdk
  • Manjaro (Arch): sudo pacman -S jre11-openjdk-headless jre11-openjdk jdk11-openjdk openjdk11-doc openjdk11-src

Set up your Android device

Follow the link to find out how to set up your device or android emulator

Next step

See hello-world to configure your project

After previous steps you can use crossbundle to build gradle project or native APK/AAB. Go to the links:

Android setup on MacOS

Install necessary packages

  1. Use crossbundle install command or download and install Android Studio.
  2. Start Android Studio, and go through the Android Studio Setup Wizard with the Custom option and install the following (or install them in SDK Manager):
    • Android SDK
    • NDK (Side by side)
    • Android SDK Command-line Tools
    • Android SDK Build-Tools
    • Android SDK Platform-tools
  3. Download and install java. Can be installed with brew through:
brew tap adoptopenjdk/openjdk
brew install --cask adoptopenjdk8

Install necessary rustup targets

Run the following command:

rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android

Add environment variables

From the Start search bar, enter ‘env’ and select Edit environment variables for your account.

Building strategyKeyValueDescription
Gradle project, native APK/AABANDROID_SDK_ROOT<path_to_sdk>\SdkCan be replaced with ANDROID_SDK_PATH and ANDROID_HOME. You might not install this env var if you used crossbundle install to set up required packages
or just want to build native APK or native AAB
Native APK/AABANDROID_NDK_ROOT<path_to_sdk>\Sdk\ndk<version>Can be replaced with ANDROID_NDK_PATH and NDK_HOME. You might not install this env var if you used crossbundle install to set up required packages
Gradle projectGRADLE_HOME<path_to_gradle>Crossbow default build process requires installed Gradle on your PC. You can download it here
Native AABBUNDLETOOL_PATH<path_to_bundletool>Download bundletool from the GitHub repository or use crossbundle install

For that edit ~/.bash_profile/~/.bashrc or ~/.zshrc files so they contain those lines:

export ANDROID_SDK_ROOT=$HOME/android/sdk
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/23.1.7779620
export GRADLE_HOME=<path_to_gradle>
export BUNDLETOOL_PATH=<path_to_bundletool>

Also, we need to make sure we have a java runtime environment (JRE) installed. We will need a key tool utility from there.
To make sure it's present type this command: ls /usr/lib/jvm/default/bin/ | grep keytool or add to your PATH env var.

Set up your Android device

Follow the link to find out how to set up your device or android emulator

Next step

See hello-world to configure your project

After previous steps you can use crossbundle to build gradle project or native APK/AAB. Go to the links:

Android setup on Docker

Build Android with Docker

Pre-requirements:

Clone this repository with this command:

git clone https://github.com/dodorare/crossbow
cd ./crossbow/

To run an example Android application with docker you will need to following steps:

Download the Docker image:

docker pull ghcr.io/dodorare/crossbundle:latest

Run the following command at the root of crossbow project:

For unix systems (Bash):

docker run --rm -it -v "$(pwd)/:/src" -w /src/examples/macroquad-permissions ghcr.io/dodorare/crossbundle build android --release

For Windows (PowerShell):

docker run --rm -it -v "${pwd}/:/src" -w /src/examples/macroquad-permissions ghcr.io/dodorare/crossbundle build android --release

Install APK on connected Android phone via USB:

Follow the link to find out how to set up your device or android emulator

adb install ./target/android/macroquad-permissions/gradle/build/outputs/apk/release/gradle-release-unsigned.apk

Or transfer APK file to your phone with any application.

iOS setup on MacOS

Setup on macOS

Install brew:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Install rust with default option:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Source binaries
echo 'source $HOME/.cargo/env' >> ~/.zshrc
source ~/.zshrc
# Or for bash
echo 'source $HOME/.cargo/env' >> ~/.bashrc
source ~/.bashrc

Install iOS targets:

# 64-bit targets (real device & simulator):
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim
# 32-bit targets (you probably don't need these & nightly only):
rustup target add armv7-apple-ios armv7s-apple-ios i386-apple-ios

Install ios-deploy for installing your app on iPhone:

brew install ios-deploy

Install Xcode from App Store.

Xcode installation

Install the necessary Xcode tools using Xcode:

  1. Start Xcode.
  2. Choose Preferences from the Xcode menu.
  3. In the Locations panel, find the Command Line Tools field.
  4. Click on the Command Line Tools and select Xcode version (you are asked for your Apple Developer login during the install process).

Login with Free Apple Developer/Apple Developer Program account:

  1. Start Xcode.
  2. Choose Preferences from the Xcode menu.
  3. In the Accounts panel, click the + sign (you are asked for your Apple Developer login during the install process).
  4. Click on Apple ID added account and find your name with (Personal team) postfix.
  5. Open Manage Certificates then click + and Apple Development.
  6. Close by clicking Done and click on Download Manual Profiles. iOS setup on MacOS

Xcode Sign in

Install crossbundle:

cargo install --git=https://github.com/dodorare/crossbow crossbundle

Build Apple app

Now everything is ready to build your application.

To simplify this example we will create a new cargo project by this command:

crossbundle new game --template bevy
cd game/

Now run the build command:

crossbundle build ios --target=x86_64-apple-ios

And if you want to run on the simulator:

crossbundle run ios --target=x86_64-apple-ios

Run your app on a real device

To run your application on a real device you will need to open Xcode and create a new project with the same bundle_identifier as your app. Then you will find a mobileprovision file in the ~/Library/MobileDevice/Provisioning\ Profiles folder (e.x: aec73e2f-c2f9-4e3b-9393-be19cc52fea3.mobileprovision).

With command security find-identity -p codesigning -v - you will get a similar result:

$ security find-identity -p codesigning -v
  1) AF96DABFC5DEE81E339ED8755DA8D1E48A87CBFE "Apple Development: <your-email>@gmail.com (TRGW43YM8W)"
     1 valid identities found

The AF96DABFC5DEE81E339ED8755DA8D1E48A87CBFE value is our sign Identity. Save it for later use.

Copy your code (in our case TRGW43YM8W) and place it in another command to get Team ID:

$ security find-certificate -c SRGWJ3YM8W -p | openssl x509 -subject
subject= /UID=A9C7ZD8H7F/CN=Apple Development: <your-email>@gmail.com (TRGW43YM8W)/OU=AS9UV719T7/O=<your name>/C=US
-----BEGIN CERTIFICATE-----
MIIFtTCCBJ2...<rest-of-private-key>

Next to OU - you will find Team ID. (in our case AS9UV719T7).

Now we are good to install our app on a real device. To run/build app for a real device you will need similar to this command to be run in your cargo project:

crossbundle run ios --release --device --profile-name=aec73e2f-c2f9-4e3b-9393-be19cc52fea3.mobileprovision --team-identifier=AS9UV719T7 --identity=AF96DABFC5DEE81E339ED8755DA8D1E48A87CBFE

Now replace test data (aec73e2f-c2f9-4e3b-9393-be19cc52fea3.mobileprovision, AS9UV719T7, AF96DABFC5DEE81E339ED8755DA8D1E48A87CBFE) - with your own and run command. If everything worked well - you will see new app on your device.

Set up your Android device

To prepare to run your Crossbow app on an Android device, you need an Android device running Android 4.1 (API level 16) or higher.

  1. Enable Developer options and USB debugging on your device. Detailed instructions are available in the Android documentation.
  2. Using a USB cable, plug your phone into your computer. If prompted on your device, authorize your computer to access your device.

Set up the Android emulator

To prepare to run and test your Crossbow app on the Android emulator, follow these steps if you want to install it from the console:

# Run following command to install System Image for Android SDK 31
crossbundle install sdkmanager --install "system-images;android-31;google_apis;x86_64"
# Run this command to create a new Pnone emulator
avdmanager create avd -n Phone -k "system-images;android-31;google_apis;x86_64"
# And finally run this command to start the emulator
emulator -avd=Phone

If you want to install it from the GUI, follow these instructions:

  1. Enable VM acceleration on your machine.
  2. Launch Android Studio, click the AVD Manager icon, and select Create Virtual Device.
  3. Choose a device definition and select Next.
  4. Select one or more system images for the Android versions you want to emulate, and select Next. An x86 or x86_64 image is recommended.
  5. Under Emulated Performance, select Hardware - GLES 2.0 to enable hardware acceleration.
  6. Verify the AVD configuration is correct, and select Finish. (For details on the above steps, see Managing AVDs)
  7. In Android Virtual Device Manager, click Run in the toolbar. The emulator starts up and displays the default canvas for your selected OS version and device.

Add environment variables

If you will build application with emulator you should add this to environment variables:

Install via command line for for macos and linux:

export PATH=<path_to_sdk>\sdk\emulator:$PATH
export PATH=<path_to_sdk>\sdk\tools\bin:$PATH

Install via command line for windows:

  • Add <path_to_sdk>\sdk\tools\bin to PATH variable.
  • Add <path_to_sdk>\sdk\emulator to PATH variable.
SETX "<path_to_sdk>\sdk\tools\bin" ~PATH~
SETX "<path_to_sdk>\sdk\emulator" ~PATH~

Overview

In this category, you will learn how to use the crossbundle tool.

Crossbundle install command

Setup packages

Use crossbundle install command to install necessary packages. To find out available commands specify the -h flag. The -h flag can be used in all subcommands crossbundle install offers.

crossbundle install -h
crossbundle install command-line-tools -h

Install tools to APK building

We offer to use our command to fast installation all required packages.

crossbundle install --preferred

This command will setup command line tools, Android platforms, build-tools, Android NDK and bundletool for AAB correct working. To provide custom installation read the article below.

Install command-line tools

If you do not need Android Studio, you can download the basic Android command line tools below. You can use the included sdkmanager to download other SDK packages.

These tools are included in Android Studio.

To see all available options use the -h flag. To install command line tools use the command:

crossbundle install command-line-tools

The command will download a zip archive and unzip command line tools into $HOME\AppData\Local\Android\Sdk\cmdline-tools\bin for windows and $HOME/Local/Android/Sdk/cmdline-tools/bin for other operating systems. Note: Android studio install cmdline tools into $SDK_ROOT/cmdline-tools/<version>/bin.

Install packages

The sdkmanager is a command-line tool that allows you to view, install, update, and uninstall packages for the Android SDK.

Also you can install packages manually. To see all available tools use the -h flag. List installed and available packages:

crossbundle install sdkmanager --list

And then enter the command.

crossbundle install sdkmanager --install "build-tools;31.0.0" "ndk;23.1.7779620" "platforms;android-31"

The command will install packages into $HOME\AppData\Local\Android\Sdk\ for Windows, $HOME/Library/Android/sdk/ for macOS, and $HOME/Android/sdk/ for Linux.

Install bundletool to AAB building

To install bundletool use command below. To see all available options use the -h flag.

crossbundle install bundletool

The command will download bundletool from GitHub repository and save it into $HOME. Notice, that you should install Java JDK to open bundletool jar file.

Crossbundle build command

Crossbundle build gradle

Crossbow default build process requires installed Gradle on your PC.

To create a project go to the example you want to build and use the command below. The command belongs to macroquad engine examples building:

crossbundle build android

# To specify custom export gradle directory
crossbundle build android --export-path=./gen/

By default build directory is target/android/<project_name>/gradle. But you can specify your own build directory via --export-path=<OUT_PATH> flag. Go to the directory where Gradle project was built and use command below to manually install APK on the device.

gradle installDebug

Also you can replace build with run subcommand to build and run APK on your device (it uses installDebug command under the hood). To see how to set android emulator check install recommendations for linux-android, macos-android, windows-android.

Crossbundle build native AAB/APK

If you don't want to use gradle you can specify it in strategy native-apk:

crossbundle build android -s=native-apk
# or do you need AAB:
crossbundle build android -s=native-aab

To find out available commands specify the -h flag.

crossbundle build android -h

Crossbundle run command

Crossbundle run gradle

Crossbow default run process requires installed Gradle on your PC.

To create a project go to the example you want to build and use the command below. The command belongs to macroquad engine examples building:

crossbundle run android

# To specify custom export gradle directory
crossbundle run android --export-path=./gen/

By default run directory is target/android/<project_name>/gradle. But you can specify your own build directory via --export-path=<OUT_PATH> flag.

Crossbundle run native AAB/APK

If you don't want to use gradle you can specify it in strategy native-apk:

crossbundle run android -s=native-apk
# or do you need AAB:
crossbundle run android -s=native-aab

To find out available commands specify the -h flag.

crossbundle run android -h

Crossbundle new command

crossbundle uses cargo-generate to generate a new project. This means that you need to install it before we proceed.

cargo install cargo-generate

Then you can create a new project:

crossbundle new project-name
# crossbundle new project-name --template bevy
# crossbundle new project-name --template quad

All supported templates you can watch here (each branch = template).

Troubleshooting

You can face the problem with Cargo.toml parsing for the generated project:

Crossbundle Tools error: FailedToFindCargoManifest("...")

To resolve this add your project name to members table of crossbow Cargo.toml:

[workspace]
members = [
    "...",
    "example/",
    "...",
]

Crossbundle update command

Crossbundle has an inner command that allows to check the version used by the user and compare it with the version in crates.io. To check the latest version of crossbundle project in crates.io use:

crossbundle update --check

If the version found in crates.io is newer than used now you can enter the command below:

crossbundle update --force

Overview

In this category, you will learn how to use the crossbow crate.

Project configuration

Сonfiguration through metadata

The easiest way to configure a project is with metadata. Here's an example of Cargo.toml:

[package]
name = "game"
version = "0.1.0"
authors = ["Example <[email protected]>"]
edition = "2021"

[dependencies]
crossbow = "0.2.3"

[package.metadata]
# The user-friendly application name for your app. Displayed in the applications menu
app_name = "Game"
# Android assets directory path relatively to project path
assets = ["assets"]
# Path to icon with `.png` format that will be provided to generate mipmap resources
icon = "path/to/icon.png"

[package.metadata.android]
# Android application wrapper: supports ndk-glue and sokol. Now ndk-glue used by bevy engine and sokol used by macroquad 
app_wrapper = "quad"
# Android targets to build on debug or release.
debug_build_targets = ["aarch64-linux-android"]
release_build_targets = ["aarch64-linux-android"]
# Android resources directory path relatively to project path
resources = ["res/android"]

# Complete support of all AndroidManifest.xml attributes
[package.metadata.android.manifest]
package = "com.example.ExampleProject"

# Adds a uses-permission element to the AndroidManifest.xml.
# Note that android_version 23 and higher, Android requires the application to request permissions at runtime
[[package.metadata.android.manifest.uses_permission]]
name = "android.permission.INTERNET"
# Specifies that an app wants a particular permission, but only if the app is installed on a device running
# Android 6.0 (API level 23) or higher. If the device is running API level 22 or lower, the app does not have the specified permission.

# See https://developer.android.com/guide/topics/manifest/uses-permission-sdk-23-element
[[package.metadata.android.manifest.uses_permission_sdk_23]]
name = "android.permission.WRITE_EXTERNAL_STORAGE"
max_sdk_version = 30

# See https://developer.android.com/guide/topics/manifest/service-element
[[package.metadata.android.manifest.service]]
name = "UpdateService"
intent_filter = []
meta_data = []

# See https://developer.android.com/guide/topics/manifest/queries-element#provider
[[package.metadata.android.manifest.queries.provider]]
authorities = "org.khronos.openxr.runtime_broker;org.khronos.openxr.system_runtime_broker"
# Note: The `name` attribute is normally not required for a queries provider, but is non-optional
# as a workaround for aapt throwing errors about missing `android:name` attribute.
# This will be made optional if/when cargo-apk migrates to aapt2.
name = "org.khronos.openxr"

# See https://developer.android.com/guide/topics/manifest/uses-feature-element
#
# Note: there can be multiple .uses_feature entries.
[[package.metadata.android.manifest.features]]
name = "android.hardware.vulkan.level"
required = true
version = 1

# See https://developer.android.com/guide/topics/manifest/meta-data-element
[[package.metadata.android.manifest.application.meta_data]]
name = "com.oculus.vr.focusaware"
value = "true"

[package.metadata.apple]
release_build_targets = ["aarch64-apple-ios", "x86_64-apple-ios"]
# The user-friendly application name for your app. Displayed in the applications menu
app_name = "Example"
# Apple targets to build on debug or release.
debug_build_targets = ["aarch64-apple-ios"]
release_build_targets = ["aarch64-apple-ios", "x86_64-apple-ios"].
# Apple resources directory path relatively to project path.
resources = ["res/apple"]

Сonfiguration through separate files

But sometimes you need to configure something more complex. For such cases, a more suitable way is to use separate AndroidManifest.xml or/and Info.plist files.

To enable this feature, you just need to add this to your Cargo.toml:

[package.metadata.android]
manifest_path = "/path/to/file"

[package.metadata.apple]
info_plist_path = "/path/to/file"

and then place AndroidManifest.xml or/and Info.plist near Cargo.toml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rust.game"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="16"
        android:targetSdkVersion="31" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application android:allowBackup="true"
        android:hasCode="false"
        android:icon="@mipmap/ic_launcher"
        android:label="Game"
        android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
        <activity android:name="com.rust.game.MainActivity"
            android:label="Game"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

That's it, this config file will be used for your mobile application.

Crossbow permissions

To request permissions with Crossbow you will need to add crossbow dependency to your Cargo.toml file. And add permissions to AndroidManifest.xml or Info.plist:

# This one:
[package.metadata]
permissions = ["camera", "microphone", "photos", "storage-read"]

# Will make the same as this one:
[[package.metadata.android.manifest.uses_permission]]
name = "android.permission.READ_EXTERNAL_STORAGE"
[[package.metadata.android.manifest.uses_permission]]
name = "android.permission.CAMERA"
[[package.metadata.android.manifest.uses_permission]]
name = "android.permission.RECORD_AUDIO"

[package.metadata.apple.info_plist]
NSCameraUsageDescription = "This app needs access to your phone's camera."
NSMicrophoneUsageDescription = "This app needs access to your phone's microphone."
NSPhotoLibraryUsageDescription = "This app needs access to your phone's photo library."

Then invoke request_async function. This function checks the permission status in the application and will request permission if it's not granted yet:

#![allow(unused)]
fn main() {
use crossbow::Permission;
let res = Permission::Camera.request_async().await?;
match res {
    Permission::Unknown => println!("Permission is in an unknown state"),
    Permission::Denied => println!("Denied by user"),
    Permission::Disabled => println!("Feature is disabled on device."),
    Permission::Granted => println!("Granted by user."),
    Permission::Restricted => println!("Restricted (only iOS)."),
}
}

Also, remember to set permissions in through Cargo.toml or Info.plist/AndroidManifest.xml files. List of required permissions for Cross-Platform Permission you can find in Permission enum.

See usage example.

Also, it's possible to request more permissions with this API:

#[cfg(target_os = "android")]
crossbow::android::permission::*;
let res = request_permission(&AndroidPermission::ReadCalendar).await?;

// or this for iOS:

#[cfg(target_os = "ios")]
crossbow::ios::permission::*;
let res = request_permission(&IosPermission::CaptureDevice(MediaType::Audio)).await;

Maybe useful

Useful commands to debug permission status in Android application using adb:

adb shell pm reset-permissions
adb shell pm list permission-groups
adb shell pm list permissions

adb shell pm grant <app package> <permission name>
adb shell pm revoke <app package> <permission name>

Crossbow Android Plugins

To write new Crossbow Android plugin - we recommend to clone this repository and use crossbow-admob as template for your plugin.

To do so, run these commands:

git clone https://github.com/dodorare/crossbow
cp -r crossbow/plugins/admob-android ./my-awesome-plugin
cd ./my-awesome-plugin

In Rust project you will need to update Cargo.toml and code in src/ folder.

Now in Android gradle project you will able to write your own Android plugin in Java or Kotlin!

Building

To build Android Gradle plugin you need to run the following command:

gradle build

Testing locally

To import your plugin into your game with Crossbow you can add following in Cargo.toml:

[[package.metadata.android.plugins_local_projects]]
include = ":my-awesome-plugin"
project_dir = "../my-awesome-plugin/android"

It will try to find your plugin by the specified path relative to your Cargo.toml.

Publishing to Github Maven repository

To publish your plugin to Github Maven repository you need to get Personal Access Token from your Github account and update information in your my-awesome-plugin/android/publish.gradle file.

To read more about Github Maven repository visit Publishing Github Maven packages.

As you setup everything - you can run the following command to publish your plugin to Maven repository:

USERNAME=<NAME> TOKEN=<TOKEN> gradle publish

To publish your plugin to crates.io - you can see this official article.

Using Published plugin

After successfully publishing your plugin you can use it in your game. To do so you will want to import it in Cargo.toml:

[dependencies]
my_awesome_plugin = "0.1.0"

[[package.metadata.android]]
plugins_remote = ["com.crossbow.awesome:my_awesome_plugin:0.1.0"]

That's it, now you can use your plugin in your game!

Overview

In this category, you will learn how to use the crossbundle tool and crossbow crate by examples and tutorials.

To get started - open Hello World example to see minimal project setup.

Hello world example

Generate a project

Generate new project with crossbundle new command!

Project overview

The project has been created. Now let's see what the project consists of.

The code below is belong to the native crossbow project with pure rust without android plugins. To see all possibilities of cargo.toml see crossbow configutarion tutorial

# Cargo.toml

[package]
name = "project-name"
version = "0.1.0"
authors = ["Example <[email protected]>"]
edition = "2021"

[dependencies]
crossbow = "*"

[package.metadata]
app_name = "My Project"
icon = "path/to/icon.png"

We decided to refuse from lib.rs file for a more convenient project configuration. We need only main.rs to deploy our code

// main.rs

fn main() {
    println!("Hello, project-name!");
}

Build an application

Let's build and run our first crossbundle application. Android commands below will generate gradle project and install apk on your device. See crossbundle run command for additional information.

cd project-name. To attach a logger when application deploys on your device use --log flag.

crossbundle run android --log

or

crossbundle run ios --log

If you want to build the application for android as native AAB - add -s=native-aab flag or add -s=native-apk to build native APK.

You will see the message: "Hello, project-name!"

In-app updates tutorial

Important: First of all you need to install crossbundle if you haven't already. See documention to install it.

Generate a project

crossbundle uses cargo-generate to generate a new project. This means that you need to install it before we proceed.

cargo install cargo-generate

Then you can create a new project:

crossbundle new project-name --template quad

All supported templates you can watch here (each branch = template).

Installation

Important: Before starting please read more about Google Play Core libraries and In-app updates.

Add Rust dependencies like this:

[dependencies]
crossbow = "0.2.3"
[target.'cfg(target_os = "android")'.dependencies]
play-core = "0.2.3"

And finally, add this to your Crossbow Android configuration:

[package.metadata.android]
plugins_remote = ["com.crossbow.play_core:play_core:0.2.3"]

That's it, now you can start using Play Core!

Usage

First step is plugin initialization. In your rust project, you will need to initialize Crossbow instance and then get Android plugin:

#![allow(unused)]
#![cfg(target_os = "android")]

fn main() {
use crossbow::android::*;
let crossbow = CrossbowInstance::new();
let play_core: play_core::PlayCorePlugin = crossbow.get_plugin()?;
}

After plugin initialization you can use supported features. For example to start connection and query purchases you can use:

#![allow(unused)]
fn main() {
play_core.check_update()?;
play_core.in_progress_update()?;
}

To read signals that plugin returns:

#![allow(unused)]
fn main() {
if let Ok(signal) = play_core.get_receiver().recv().await {
    println!("Signal: {:?}", signal);
}
}

Complete documentation of plugin you can find here.

Build an application

Let's build and run this application. Android command below will generate gradle project and install apk on your device. See crossbundle run command for additional information.

crossbundle run android

But to be able to test In-app updates - you will need to publish your application to Play Store as Internal testing or any other (Closed testing or Production, etc.).

To publish your app to Play Store - you will want to export gradle project with this command:

crossbundle build android --export-path=./path/

Then in generated project add signing to build.gradle like this:

signingConfigs {
    release {
        if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
            storeFile file(MYAPP_UPLOAD_STORE_FILE)
            storePassword MYAPP_UPLOAD_STORE_PASSWORD
            keyAlias MYAPP_UPLOAD_KEY_ALIAS
            keyPassword MYAPP_UPLOAD_KEY_PASSWORD
        }
    }
}
buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

and in gradle.properties actual values:

MYAPP_UPLOAD_STORE_FILE=my-project.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-project
MYAPP_UPLOAD_STORE_PASSWORD=123456
MYAPP_UPLOAD_KEY_PASSWORD=123456

You can read more here, and here.

Google Play Billing tutorial

Important: First of all you need to install crossbundle if you haven't already. See documention to install it.

Generate a project

crossbundle uses cargo-generate to generate a new project. This means that you need to install it before we proceed.

cargo install cargo-generate

Then you can create a new project:

crossbundle new project-name --template quad

All supported templates you can watch here (each branch = template).

Installation

Important: Before using this plugin please follow instructions on Getting ready Google Play Billing official guide.

Just add Rust dependencies like this:

[dependencies]
crossbow = "0.2.3"
[target.'cfg(target_os = "android")'.dependencies]
play-billing = "0.2.3"

And finally, add this to your Crossbow Android configuration:

[package.metadata.android]
plugins_remote = ["com.crossbow.play_billing:play_billing:0.2.3"]

That's it, now you can start using Play Billing!

Usage

First step is plugin initialization. In your rust project, you will need to initialize Crossbow instance and then get Android plugin:

#![allow(unused)]
#![cfg(target_os = "android")]

fn main() {
use crossbow::android::*;
let crossbow = CrossbowInstance::new();
let play_billing: play_billing::PlayBillingPlugin = crossbow.get_plugin()?;
}

After plugin initialization you can use supported features. For example to start connection and query purchases you can use:

#![allow(unused)]
fn main() {
play_billing.start_connection()?;
play_billing.query_purchases("YOUR_TYPE")?;
}

To read signals:

#![allow(unused)]
fn main() {
if let Ok(signal) = play_billing.get_receiver().recv().await {
    println!("Signal: {:?}", signal);
}
}

Complete documentation you can find here.

Build an application

Important: Read officialtutorial on how to test Google Play Billing for more information here.

Let's build and run this application. Android command below will generate gradle project and install apk on your device. See crossbundle run command for additional information.

crossbundle run android

But to be able to test In-app purchases - you will need to add Products in Google Play Console. And then build and sign your app with your generated keystore.

To publish your app to Play Store Internal Testing - you will want to export gradle project with this command:

crossbundle build android --export-path=./path/

Then in generated project add signing to build.gradle like this:

signingConfigs {
    release {
        if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
            storeFile file(MYAPP_UPLOAD_STORE_FILE)
            storePassword MYAPP_UPLOAD_STORE_PASSWORD
            keyAlias MYAPP_UPLOAD_KEY_ALIAS
            keyPassword MYAPP_UPLOAD_KEY_PASSWORD
        }
    }
}
buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

and in gradle.properties actual values:

MYAPP_UPLOAD_STORE_FILE=my-project.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-project
MYAPP_UPLOAD_STORE_PASSWORD=123456
MYAPP_UPLOAD_KEY_PASSWORD=123456

You can read more here, and here.

Fastlane automation for Android

We want to make you work less on the hard stuff behind the automation of publishing Rust mobile apps so we prepared some best practices on how you can automate the boring stuff with our creator Fastlane plugin. You can read more about Fastlane here.

Setup

First of all, we would suggest you pass through our crossbow basic tutorials for Android or/and iOS.

After you got familiar with crossbow you can get to the following steps to run Fastlane locally:

  1. Make sure you have crossbundle installed.
  2. Install Fastlane.
  3. Setup XCode or Android Studio depending on which platform you want to run your workflow.
  4. Create a test project (you can use our template) or add Fastlane to your project.
  5. Install our fastlane plugin with the next command fastlane add_plugin crossbow.

Setup for Play Market

  1. Open Google Play Console (you will need a developer account for this).
  2. Click on the button "Create app" Create app and specify your application data in the form.
  3. Generate signing key through Android Studio as shown in this official tutorial.
  4. Generate a "Play Store Json Key" for Fastlane as shown here.
  5. Configure corresponding variables in fastlane/Fastfile file.

Run lane

To run our Fastlane pipeline just call fastlane android or fastlane ios at the root of the project.

Please note, Fastlane will ask you to log in on the first run to configure the setup.

See results

After the successful finish of publishing as an internal testing draft, you should see your release on the Google Play Console. Find section "Testing" and click on the "Internal testing". You will see something like this:

Internal testing

Feel free to add some other lanes to fill your needs, here's the full list of them.

If you found a bug or issue - you can find or create an issue in this repository.

Using subxt with bevy engine

  1. You need to install crossbundle if you haven't already. See documention to install it and configure your project.

  2. Specify subxt crate and bevy in your Cargo.toml. We prefer to use versions below:

[dependencies]
subxt = "0.23"
bevy = "0.8.1"

You might need additional dependencies to write your code. See examples/bevy-explorer/cargo.toml

Bevy explorer example

To learn how to use subxt with bevy engine, you can go to the examples/bevy-explorer or install bevy explorer template. Follow next steps:

  1. Install cargo-generate:
cargo install cargo-generate
  1. Install bevy-explorer template:
crossbundle new example --template=bevy-explorer
  1. After previous steps, now you can install the application on the device.

Installing application on the device

You can deploy the application on your device or android emulator with commands below. At first, you should go to example directory. Use it:

Bash:

If the template was installed

cd example

If bevy-explorer example will be used

cd example/bevy-explorer

By default crossbundle build android command will generate gradle project and install apk on your device. To build native .apk and .aab see commands below. To build native APK and run it on the device using the command. If you want to build an application replaces run with build.

crossbundle run android -s=native-apk

or

crossbundle run ios

To build native AAB and run it on the device using the command. If you want to build an application replaces run with build.

crossbundle run android -s=native-aab

Contributing

If you want to help us build an awesome Cross-Platform future for Rust Games, please reach out! We need all the help we can get:

Also, read testing guide to run tests in crossbow.

How to Contribute Code

Would you like to contribute code to Crossbow? Here's how!

  1. Fork the dodorare/crossbow repository on GitHub, you'll need to create a GitHub account if you don't have one already.*
  2. Make your changes in a local clone of your fork.
  3. For a higher chance of CI passing the first time, consider run these commands from the root of your local clone:
    1. cargo fmt --all -- --check (remove --check to let the command fix found problems)
    2. cargo clippy --all-targets --all-features -- -D warnings -A clippy::unnecessary-unwrap -A clippy::too-many-arguments
    3. cargo test --all-targets --workspace
  4. Push your changes to your fork and open a Pull Request.
  5. Respond to any CI failures or review feedback.

The same steps apply for any other repository in the organization that you would like to contribute to.

How to Contribute Docs

Crossbow Documentation

If you want to contribute to this documentation, please see the Contributing section.

  1. Fork the dodorare/crossbow repository on GitHub, you'll need to create a GitHub account if you don't have one already.*
  2. Install mdBook.
  3. In the "docs/" directory, run mdbook serve --open and make your changes in a local clone of your fork.
  4. Push your changes to your fork and open a Pull Request.
  5. Respond to any CI failures or review feedback.

That's all, big thanks for contributing!

The same steps apply for any other repository in the organization that you would like to contribute to.

Testing guide

How to run tests in crossbow

In crossbow, we have unit tests, integration tests, and examples. To run tests, you will need to set up an Android and Apple environment (you can find more information in installation category).

If you want to run tests for our crossbundle crate, you can make it by the following steps: download this repository, proceed to the crossbundle/tools directory, and run cargo test. It will run all tests for the crossbundle-tools crate that is primarily used by crossbundle.

In case of issues

Feel free to open Github Issues - we will be happy to fix or review them.

Contributors

Here is a list of the contributors who have helped improving Crossbow. Big shout-out to them!

Development Roadmap

NumberTitleSpecificationStatus
1.Support AABAdd support of generation AAB file. Android App Bundle is a publishing format that includes all your app’s compiled code and resources.
2.Support Macroquad engineAdd support of Macroquad engine. We will change our crossbundle command-line tool to support Android and iOS building of Macroquad.
3.Support Android PluginsAdd support of Android plugins to help add additional functionality provided by the Android platform and ecosystem (like Ads, Auth, In-app purchases, etc.). Something similar to Godot Android plugins.
4.Support Cross-platform permissionsProvide a single cross-platform permission API that works with any iOS, Android, etc application that can be accessed from shared code no matter how the user interface is created.
5.Simple installationSimple installation with environment variables, libs, etc. Make installation of Android SDK, NDK, tools more robust.
6.Support iOS PluginsAdd support of iOS plugins to help add additional functionality provided by the Apple platforms and ecosystem (like Ads, Auth, In-app purchases, etc.). Something similar to Godot iOS plugins.🛠
7.Sign in with GoogleAdd support of Google Sign In inside any application.
8.Sign in with AppleAdd support of Apple Sign In inside any application.📝
9.Better support for Apple xcrun, xcode projAdd better support and rust wrappers for Apple xcode tools, xcrun. Make cool xcode project generation library.📝
10.Apple Game CenterAdd Apple Game Center support.📝
11.Android In-App purchases & Google Play BillingAdd support for Google Play Billing. Make it possible to buy items from your application.
12.Support Apple In-App purchasesSupport Apple StoreKit. Make it possible to buy items from your application.📝
13.Support Android In-App updatesAdd support for Android In-App updates.

✅ = Works and tested — 🆗 = Works but may contain bugs — 🛠 = Under development — 📝 = Planned

  • https://developers.google.com/games/services/common/concepts/sign-in
  • https://developers.google.com/games/services/downloads/sdks
  • https://developers.google.com/games/services/cpp/GettingStartedNativeClient
  • https://developers.google.com/identity/sign-in/web/build-button
  • https://github.com/cgisca/PGSGP
  • https://docs.godotengine.org/en/stable/tutorials/platform/ios/ios_plugin.html
  • https://github.com/polyhorn/simctl
  • https://docs.godotengine.org/en/stable/tutorials/plugins/android/android_plugin.html
  • https://github.com/godotengine/godot-google-play-billing
  • https://github.com/google/play-unity-plugins
  • https://android.googlesource.com/platform/frameworks/opt/gamesdk
  • https://developer.android.com/games/develop/permissions
  • https://docs.microsoft.com/en-gb/xamarin/essentials
  • https://docs.microsoft.com/en-us/xamarin/essentials/permissions

Special Thanks

This project initially funded by Web3 Foundation Grants Program. Big shout-out to them!

If you want to support this project - contact us on our corporate email: [email protected].