avatarKofi Otuo

Summary

The provided content is a comprehensive guide on integrating Rust programming language into Android application development, aimed at simplifying the process for beginners without requiring knowledge of C, C++, or JNI.

Abstract

The article "Integrating Rust With Android Development" introduces Rust as a memory-safe alternative to C and C++ for Android app development. It acknowledges the scarcity of beginner-friendly resources on the topic and aims to fill that gap by providing a step-by-step walkthrough using Android Studio. The guide covers setting up the Rust plugin, creating a new Rust library project, adding dependencies, generating build files, and configuring toolchains and linkers for Rust to Android compilation. It also demonstrates how to automate the build process with Gradle and log Rust code within Android applications. The tutorial emphasizes ease of use and is designed to become the go-to resource for developers looking to incorporate Rust into their Android projects.

Opinions

  • The author believes that integrating Rust into Android development can be simplified for beginners, despite the complexity of existing documentation.
  • The tutorial is presented as a straightforward and efficient method, suggesting that the current state of resources is inadequate for newcomers to the field.
  • The author expresses that the Rust programming language is superior for systems programming due to its memory safety features compared to C and C++.
  • By providing a detailed guide, the author implies that the process of integrating Rust with Android can be made accessible to a wider audience of developers.
  • The article suggests that the use of tools like flapigen and rifgen can streamline the development process by automating the generation of interface files and reducing manual updates.
  • The author encourages reader engagement and support by inviting them to buy him a coffee, indicating a personal investment in the tutorial's usefulness and community feedback.

Integrating Rust With Android Development

Rust is a general-purpose, systems programming language that has been around for quite some time now. Being a systems programming language, it can be used to perform tasks similar to languages such as C and C++ but with much more memory safety. This allows Rust to be used to write programs or scripts on numerous operating systems including Android. You may wonder how this could be possible and if there is a simple way to do so. Well, that’s what this article is about!

Currently, there isn’t much information on how to write Rust code for an android application. There is some information provided by Google here but it’s complicated for a beginner to understand. The goal of this walkthrough is to provide a simple but efficient guide to integrating Rust code with android development and ultimately become the go-to guide. No prior knowledge of C or C++ or JNI is required!

We will use Android Studio. Let’s begin by setting it up.

Setup 🌱

Rust Plugin ⚙️

First, we need the Rust plugin. Open up Android Studio. A dialog similar to what is displayed below would open up. Select the Plugins tab, search for “Rust” and then install the official Rust plugin by JetBrains. Alternatively, if you have a project already opened, click on File at the top left corner of Android Studio and select Settings. Click on Plugins.

The Rust Plugin requires Rust installed on your system. You can follow this link to install Rust on your system.

Creating An Empty Application 📱

Now let’s create a new empty app. Start by going through the standard new project setup.

Let’s name our project Rust Application and click on finish.

A window similar to the one shown below would appear.

Incorporating A Cargo Project 💼

Let’s now add a Cargo project, following the tutorial provided here. To embed a Rust project, simply click on the Terminal in Android Studio and type cargo new rust_lib --lib, then press enter.

C:\Users\USER1\AndroidStudioProjects\RustApplication>cargo new rust_lib --lib

This creates a new library so it can be used from within our application. We named the library rust_lib. Take note of where the folder is created.

To view the folder in Android Studio, navigate to the Project pane and select Project from the dropdown menu instead of Android.

You would then see a new folder named rust_lib. This folder contains a new git repository by default, a Cargo.toml file, and an src folder containing lib.rs. Now let’s modify the type of library we just created using the Cargo.toml file. For mobile app development, the library should be a dynamic one.

Add the following to the contents of the Cargo.toml file.

[lib]
name = "rust_lib"
crate-type = ["cdylib"]

View the gist here.

Adding Dependencies 🧶

Let’s add dependencies that would create the necessary files to make linking our rust code to the Android end a smooth process.

Use the “*” to pull the latest version of the dependency.

de>flapigen is the main build dependency to generate the appropriate code from our rust code to use it in our android app. flapigen works with an interface file but having to modify the interface file every time there’s a code change could get tedious. That’s where de>rifgen comes it. It makes the creation of the interface file such a breeze.

The extra dependencies are for logging.

Creating A Build File 📄

As mentioned earlier, flapigen and rifgen are build dependencies and interact with the build.rs file. Right-click on rust_lib folder and select New > Rust File.

Name the file build.rs.

Following the tutorial given by flapigen and rifgen, our build.rs should look similar to the following:

You might be wondering what’s happening in the build.rs. flapigen converts what’s in the interface file to a java_glue rust file. So we first specify the source file for the interface file (in_src) and then the out file (java_glue.rs). The directory of the java_glue.rs has to be the same as the OUT_DIR environment variable. After doing that, use rifgen to generate the interface file, specifying our preference depending on the language we’re adding the rust project to. The last parameter of Generator::new specifies the start of the folder containing our rust code and the generate_interface function takes the path of the interface file. i.e. in_scr. The java_folder specifies where the java files created should go to. Calling swig_gen.expand tells flapigen to generate the appropriate files. Note these parameters as we use them in the Gradle build.

Finally, create a file named java_glue.rs in the rust_lib/src folder and put the following contents:

And add:

mod java_glue;
pub use crate::java_glue::*;

To your lib.rs file. Doing this connects your rust code to the one generated.

Add Android Toolchains And Linkers ⛓

To compile Rust for android, we need to add the android toolchains to rustup. To do so, simply run the following in the Terminal:

>rustup default nightly
>rustup target add aarch64-linux-android armv7-linux-androideabi

Since the rifgen crate works with nightly, you’ve to install Rust nightly first.

Then you add the rust toolchains and standard library for 64-bit and 32-bit android versions respectively. Now, let’s add the compiler linkers. It should be added to rust_lib/.cargo/config.toml file.

Right-click on the rust_lib folder, create a new directory called .cargo then create a new file in the .cargo directory called config.toml.

The appropriate linkers come with Android NDK and should therefore be downloaded before continuing.

Add the following to the config file you created.

Replace ANDROID SDK with the android SDK path (or the folder containing the NDK-bundle). Also, replace the OS VERSION with your OS version. For instance, on my Windows pc, the full path is:

[target.aarch64-linux-android]
linker = "C:\\Users\\taimoor\\AppData\\Local\\Android\\Sdk\\ndk-bundle\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\aarch64-linux-android21-clang++.cmd"

Notice the .cmd at the end for a Windows build.

If you’re using Mac OS with NDK v25, you may face an issue. If you do face an issue, you can try previous versions of the NDK. Alternatively, you can contact more for more assistance.

Using Gradle To Automate Build 🐘

Gradle can be used to automatically run cargo build whenever we want to test out the app. This would cause changes we made at the Rust side to be automatically updated into our application.

Note that this is the app or module level Gradle file and not the Project level Gradle file. Add lines 20 to 27 and line 65 onwards. Line 65 onwards just instructs Gradle to run cargo build whenever we run the app. After running the cargo build command, we then copy the java files and the dynamic library file (.so) created and paste them into the directory which can be read by Android and used in our Kotlin code.

The application now should run 😄. If you’re having difficulty running it, leave a comment below or feel free to mail me at [email protected]!

Bonus Section: Logging 📃

Let’s quickly implement logging to help with debugging our Rust code. In the lib.rs file, add the following content:

We use the android_logger crate for generating logs and then call log_panics::init() to redirect all panics to be logged rather than printed to standard error. Notice the attribute #[generate_interface]. This tells rifgen that we’re going to call this function from Kotlin so it should add that method call to the interface file.

Enjoying this tutorial? Why not buy me a coffee? ☕️

Loading The Library From Kotlin 📲

Now that we have set up the Rust side, let’s move on to the Kotlin side. We will now load the library from a singleton:

Add the various import for the Logs class we created. Note how even though we named the function initialise_logging, we’re able to use it as initialiseLogging. This is because we specified CamelCase when setting up rifgen.

Run the program to see the information from the Rust code being logged.

Next Steps 🍀

That concludes the first part of this series. In the next part, we would mix our Rust code with some GUI to finalize this walkthrough.

References

Repository

Rust
Android App Development
Java
Programming
Android
Recommended from ReadMedium