Android / iOS app with shared Rust logic

Overview

Rust core for native Android and iOS apps

Rust Android [TODO iOS badge]

This is an example that shows how to use a shared Rust core in native Android and iOS apps.

⚠️ Looking for maintainers. If you want to help, just open an issue, or email me [email protected]

Why?

This approach gives us the best of all worlds: we prevent code duplication by using a shared library. Rust, as a highly performant and safe language is a great fit for mobile. We keep a fully native UI experience and uncomplicated access to the latest APIs of the platforms.

It's also very flexible, allowing to migrate easily between different platforms, including conventional cross-platform frameworks like Flutter or React Native. For example, you can develop your MVP with Rust+React Native or Rust+Flutter, and migrate later to native iOS/Android, without having to rewrite everything. You even can reuse your core for a web-app, using WebAssembly, or desktop app (where again, you can use native or a cross-platform framework like Electron).

Project structure

  • Rust: Repo's root.
  • iOS app: ios_app directory.
  • Android app: Repo's root as well. TODO move it to a folder android_app, like the iOS app.

Possible setups

There are different ways to integrate Rust:

As source (like in this repo)

  • Simple setup.

  • Rust is built as part of the app's build process.

  • Not ideal if there are team members unfamiliar with Rust.

As binary

The Rust binary is distributed as an external dependency.

  • Better for teams with different skillsets. Everyone works mainly with their familiar tech stack.

  • Better separation of concerns / modularity.

  • Considerably more complicated to setup than monorepo (has to be done only once though).

  • Rust binaries have to be versioned and released.

Note: it is possible to overwrite the external dependency with a local copy for local development.

As "normal" library

Here the external dependency contains the Rust binary and wrapper libraries for Android and iOS respectively (written in Kotlin and Swift), which hide the FFI/JNI, providing a simple and safe interface to the apps. This makes working with this dependency like with regular third parties.

An example for this and the binary approaches can be found here. The Android build contains a wrapper library, which is imported in the Android app with Gradle. The iOS build is distributed directly as a binary (no wrapper), using Carthage.

Note on concurrency

While it's possible to use asynchronous code in core, it's recommended to use blocking apis and add concurrency in the apps. This simplifies the FFI/JNI interfaces (see the CoEpi example, where the apps add concurrency via RxSwift/RxJava).

"Real world" examples

CoEpi

A mobile contact tracing app for epidemics, with Android and iOS frontends.

Xi editor

A text editor with a lot of frontends: MacOS, GTK, Electron and Windows, among others.

Other related projects

WASM-Rust-d3 example

An example that shows how to display chart data with d3/JS, using a Rust core to fetch it.

yew-d3-example

Similar to the above, but using the Yew framework

Quickstart

Install rustup

Android specific steps

  • Ensure the NDK is installed.

  • Set the NDK_HOME environment variable with path to the NDK, e.g:

export $NDK_HOME=$HOME/Library/Android/sdk/ndk/21.3.6528147/
cargo install cargo-ndk
  • Add targets
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android
  • Run the project in Android Studio. This will build Rust, put the binaries in the correct place and start the app.

iOS specific steps

  • Install rust-bitcode 1.46.0 with macOS binary support
wget https://github.com/getditto/rust-bitcode/releases/download/v1.46.0/rust-ios-arm64-1.46.0.zip
unzip rust-ios-arm64-1.46.0.zip
cd rust-ios-arm64-1.46.0
./install.sh

As the binaries are not signed, you'll have to convince macOS that it's safe to run them. One solution is to do the following:

  1. cd rust_android_ios/ios_app
  2. cargo +ios-arm64-1.46.0 build --target aarch64-apple-ios --release --lib
  3. if it fails because macOS doesn't trust the binary, go to System Preferences -> Security & Privacy and Allow to run binary then go to 2.
  • Run the project in Xcode. This will build Rust, put the binaries in the correct place and start the app.

Android specifics

  • Logcat doesn't show stdout and stderr, which means that you'll not see println or panic messages (unless specially configured, like done in this repo).
  • If you're having difficulties, try reproducing the problem in a plain (non Android) Kotlin (or Java) project. The JNI is the same, but it's easier to debug, among other things, because you can see stdout/stderr.

iOS

  • iOS shows stdout/stderr as expected and is overall easier to worth with than Android, given the simpler FFI api.

Inspecting binaries

There are diverse tools to inspect the binaries, e.g.

nm -g libcore.so

Shows the external symbols, useful if you want to check that the library was generated correctly / contains the symbols from your sources.

To look for a specific symbol:

nm -g libcore.so | grep greet

Convenience

iOS

  • cbindgen: generates headers for the FFI Rust declarations. In this project, this would mean that mobileapp-ios.h would be automatically generated.

Android

  • rust-swig: similarly to cbindgen for iOS, this generates the JNI api for the Rust declarations. In this project, this would mean that JNIApi would be generated, and ffi_android.rs mostly too.

Links

Official Rust FFI docs

Rust FFI guide

Official JNI docs (tutorials may be better to start...)

Android JNI tips

Android supported ABIs

Contribute

  1. Fork
  2. Commit changes to a branch in your fork
  3. Push your code and make a pull request
Comments
  • iOS dependencies

    iOS dependencies

    Hey!

    Awesome project! I'm trying to run the iOS app (haven't tried Android yet) and I'm having some issues. Is there anything not in the README that's needed?

    I'm running on stable.

    When I run the iOS app in XCode I get

    + RUSTFLAGS='-Z embed-bitcode'
    + cargo +ios-arm64 build --target aarch64-apple-ios --release --lib
    error: no such subcommand: `+ios-arm64`
    + cargo build --target=x86_64-apple-ios --release
       Compiling log v0.4.8
       Compiling libc v0.2.60
       Compiling core-foundation-sys v0.6.2
       Compiling cfg-if v0.1.9
    error[E0463]: can't find crate for `core`
      |
      = note: the `x86_64-apple-ios` target may not be installed
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0463`.
    error: could not compile `cfg-if`
    
    To learn more, run the command again with --verbose.
    warning: build failed, waiting for other jobs to finish...
    error: linking with `cc` failed: exit code: 1
    

    I have installed x86_64-apple-ios and aarch64-apple-ios.

    opened by AxelNilsson 14
  • Few questions regarding for Android

    Few questions regarding for Android

    Hi I have some questions regarding for the development of Android using the crate:

    1. Am I able to make GUI applications?
    2. Is there too much biolerplate code in it or is it simple and clean?
    3. Is it easy to use or harder to use over something like Flutter or Android app Studio?
    opened by Joe23232 4
  • Big Sur, XCode 12.5.1, link fails

    Big Sur, XCode 12.5.1, link fails

    ld: library not found for -lSystem
    

    Workaround is to add this block to ios_app/build-rust-xcode.sh

    # From https://github.com/TimNN/cargo-lipo/issues/41#issuecomment-774793892
    if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then
      # Assume we're in Xcode, which means we're probably cross-compiling.
      # In this case, we need to add an extra library search path for build scripts and proc-macros,
      # which run on the host instead of the target.
      # (macOS Big Sur does not have linkable libraries in /usr/lib/.)
      export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}"
    fi
    
    opened by rjrjr 1
  • Requires Android NDK 22

    Requires Android NDK 22

    Due to https://github.com/rust-lang/rust/pull/85806, this is broken by the last Android NDK (23). Symptom is failed link, unable to find library -lgcc.

    Workaround is simple enough, downgrade to NDK22, e.g.

    export NDK_HOME=${ANDROID_SDK_ROOT}/ndk/22.1.7171670
    

    Might want to make a note in the README?

    opened by rjrjr 0
  • Flutter

    Flutter

    I've been designing a Rust library for usage with Flutter. I see that you're doing Kotlin/Java <-> Rust here, but you mention Flutter.

    Is there a plan to make a template for Flutter? Because there are 2 methods to consider: FFI vs Plugin call. Since plugin calls are very slow, FFI should be prefered, but what to do when Rust needs JNI objects? You can't pass them through Flutter's FFI

    opened by lattice0 3
Owner
null
iOS app example - AI Selfies Generator like Lensa: Stable Diffusion In Action

Magic Avatars In this repository, we look at several approaches to creating avatars, changing backgrounds, and deep image processing for more detailed

Perpetio 3 Jan 17, 2023
Using Rust to create an iOS static library

ObjCrust A modified ObjCrust which uses Rust cross-compiler. Cross-compiler needs to be built first (note: it is on a separate branch now, so don't fo

Valerii Hiora 39 May 10, 2021
Fable Rust Raytracer - iOS version

Fable Rust Raytracer - iOS version Originally made by @ncave (https://github.com/ncave/fable-raytracer), port to iOS by @delneg Pre-requisites Rust, b

Denis 4 May 2, 2022
Cargo subcommand to automatically create universal libraries for iOS.

cargo lipo Provides a cargo lipo subcommand which automatically creates a universal library for use with your iOS application. Maintenance Status Plea

Tim Neumann 430 Dec 29, 2022
A Rust crate to load a shared library into a target process without using ptrace.

Intruducer A Rust crate to load a shared library into a target process without using ptrace. This is a portable rewrite of dlinject. Compatibility It

null 90 Jan 3, 2023
Glue between Rust and Android

deprecated in favor of https://github.com/rust-windowing/android-ndk-rs which works with winit master Android Glue Usage With Docker The easiest way t

Rust Windowing 898 Dec 15, 2022
Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery life of your device.

Universal Android Debloater GUI DISCLAIMER: Use it at your own risk. I am not responsible for anything that could happen to your phone. This software

w1nst0n 7k Jan 7, 2023
🤖🦀 A rust native replacement for Android's `sdkmanager`

???? A rust native replacement for Android's `sdkmanager`

Traverse Research 13 Dec 13, 2022
Android-related tools for building and developing applications 🛠

Rust Android Tools Android-related tools for building and developing applications: Name Description Status aapt2 Android Asset Packaging Tool ✅ bundle

DodoRare 6 Dec 31, 2022
android-pathfinding

android-pathfinding Android pathfinding dependencies { implementation 'com.github.planet0104:android-pathfinding:1.0.0' } int[][] grid = new i

Jia Ye 1 Dec 17, 2021
Android resource file parsing & writing

arsc arsc is a Rust library that provides the ability to parse and write Android resource file (arsc) [dependencies] arsc = "0.1" Compiler support: ru

Yaxin Cheng 7 Dec 25, 2022
An Android application for ruffle.rs

This is a native Android application for Ruffle. It is in a very early stage. Prebuilt APKs The latest (successful) Actions run (here) should have a d

TÖRÖK Attila 28 Dec 21, 2022
Run all your Linux graphical apps on Android 💖✨✨✨

Waylovely Run all your Linux graphical apps on Android ?? ✨ ✨ ✨ The Android windowing system is different than those in desktop operating systems. In

Waylovely Project 14 Nov 23, 2022
Tokio based client library for the Android Debug Bridge (adb) based on mozdevice

forensic-adb Tokio based client library for the Android Debug Bridge (adb) based on mozdevice for Rust. Documentation This code has been extracted fro

null 6 Mar 31, 2023
rust on pebble - functional with limited capabilities

Pebble.rs Pebble.rs is a crate that allows rust to be used to develop Pebble applications. It is compatible with SDK 3.0 and is known to work on the a

Andrew Foote 44 Aug 13, 2022
APK manifest & resources parser in Rust.

BXMLRS bxmlrs is a Rust library (WIP) for parsing binary Android XML files (AndroidManifest.xml). Usage use bxmlrs::parser; use quick_xml::reader::Rea

null 6 Oct 21, 2023
Android / iOS app with shared Rust logic

Rust core for native Android and iOS apps [TODO iOS badge] This is an example that shows how to use a shared Rust core in native Android and iOS apps.

null 193 Dec 5, 2022
Shared memory - A Rust wrapper around native shared memory for Linux and Windows

shared_memory A crate that allows you to share memory between processes. This crate provides lightweight wrappers around shared memory APIs in an OS a

elast0ny 274 Dec 29, 2022
A simple library for use one Rust code in multi platforms such as WebAssembly, Android and iOS

chameleon chameleon is a simple library for use one Rust code in multi platforms such as WebAssembly, Android and iOS. Key Features TBA Quick Start TB

Chris Ohk 3 Oct 18, 2021
A lightweight, embedded key-value database for mobile clients (i.e., iOS, Android), written in Rust.

A lightweight, embedded key-value database for mobile clients (i.e., iOS, Android), written in Rust. ⚠️ Still in testing, not yet ready for production

Tangent 6 Sep 25, 2023