Tauri - The Flutter killer?
Tags: javascript, rust, mobile, crossplatform
Published: 2023-02-19 18:06:26

## What is Tauri?
Tauri is an open-source framework for building cross-platform desktop applications using web technologies such as HTML, CSS, and JavaScript.

Tauri has been in front of the scene these times and was considered as one of the best option to build desktop apps along [Flutter](https://flutter.dev/) but hasn't get to mobile development yet!

Now a new era begins 👑! Tauri is now able to build with the same codebase, apps for mobile. Through this article i will help you configure a project to build for Android devices.

## My environment

For the purpose of this article, i will be using:
- A macbook pro M1 ARM Chip with MacOS Ventura 13.2
- A terminal with [fish shell](https://fishshell.com/) and [Homebrew](https://brew.sh/) installed
- An android device running on Android 12

## Tauri Mobile 
On the [Tauri Blog](https://tauri.app/blog/2022/12/09/tauri-mobile-alpha/), they've announced an alpha release of Tauri mobile. In this article, i will help you create your first app with it! Let's dive in! 🏊‍♀️

## Android Pre-requisites
### Java Development Kit (JDK)
In order to build our android app, we need to install first the [JDK](https://www.oracle.com/java/technologies/javase/jdk13-archive-downloads.html). And again, feel free to select the one that suits your OS.

### Android SDK
As we are building an app for android, we need the android SDK tools. It will helps us to build and test Android apps, and to publish your finished app to the Google Play Store or other app markets. 

The easiest way to install it is to download [Android Studio](https://developer.android.com/studio). Head over to their website 👆 and click on the `Download` button. Click on the agreement button and select the right version for your computer, in my case for example, i've downloaded the one for the mac with Apple chip.


![Android studio download pop-up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0jecnvyjxuvbt9g6mdp.png)

When your download is finished, install it by double-clicking on the file. Leave all default option and download the latest SDK as the software ask you. To make sure that everything is ok, let's open the `settings` represented by a three dot button next to the `open` button and select `SDK Manager`. 

You should see something like this:

![SDK Manager](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9jwt0oe8h5ewqgnstyq.png)

Download the one corresponding to your Android device if it's not already installed. Then we'll head over to the `SDK Tools` tab then select:
- Android SDK Command-line Tools (latest)
- NDK (Side by side)
- Android SDK Build-Tools
- Android SDK Platform-Tools


![SDK Tools Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjspbipviipbbkb1l6xx.png)

Then click on the `Apply` button.
Now that we've done that, we can close Android Studio for now.

### Environment variables
Now we need to specify some environment variables. Please feel free to search on the internet how to do it for your OS.

In my case, i'm using a mac with a fish shell (i can write an article on that if you are interested 😉)  installed on it so my command will be `code ~/.config/fish/config.fish` to add environment variables. My file will be like this:
```bash
if status is-interactive
    # Commands to run in interactive sessions can go here
end
if status --is-login
    set -gx ANDROID_SDK_ROOT $HOME/Library/Android/sdk
    set -gx NDK_HOME $HOME/Library/Android/sdk/ndk/25.1.8937393
end
``` 
⚠️ After having doing this, i suggest you to close your terminal and open a new one to enable changes.

As you can see, i've added those 2 variables: ` ANDROID_SDK_ROOT and NDK_HOME`. Change these values according to your paths.

Still following 😅? I know this can be frustrating doing all these configs but believe me, good days are coming! Now that we've done the Android specific configuration, let's install `tauri` 🥵  

## Install Tauri for mobile

### Pre-requisites
The [tauri documentation](https://tauri.app/v1/guides/getting-started/prerequisites) is clear enough to get along yourself without any extra help.

### Prepare Tauri for mobile development 
Please head over their [documentation](https://next--tauri.netlify.app/next/guides/getting-started/prerequisites) to prepare your workspace as i think it's already clear and easy to begin with.

### Create your application
From here, i'd ask you to follow along carefully to avoid getting lost.

Let's start by creating a simple Vite app:
```bash
> pnpm create vite
```

You will be asked some informations like:
- the name of your project (i chose "taurituto")
- the framework you will use (i chose React with TypeScript)

Install required packages with 

```bash
> pnpm i
```

You should have something as similar as this:

![frontend project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wqegr3xjpxxjrlz91is.png)

Nothing special if you are familiar with Vite apps.

Let's do some configurations before adding our Tauri app. 

### Vite config

As Tauri will run this Vite app on our mobile app, we need to set it up so it can display our content using our computer port and IP address. 

Let's see what we got inside our `vite.config.ts` file for now:

```js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
})

```

Like mentioned on this [documentation](https://next--tauri.netlify.app/next/guides/getting-started/setup/vite), we need to change this file in order to run our Vite into the mobile app. First, we need to install `internal-ip`, you know the drill:

```bash
pnpm i -D internal-ip
```

And change our `vite.config.ts` to use it:
```js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { internalIpV4 } from 'internal-ip'

// https://vitejs.dev/config/
export default defineConfig(async () => {
  const host = await internalIpV4();
  return {
    // prevent vite from obscuring rust errors
    plugins: [react()],
    clearScreen: false,
    server: {
      host: '0.0.0.0', // listen on all addresses
      port: 5173,
      // Tauri expects a fixed port, fail if that port is not available
      strictPort: true,
      hmr: {
        protocol: 'ws',
        host,
        port: 5183
      },
    },
    // to make use of `TAURI_PLATFORM`, `TAURI_ARCH`, `TAURI_FAMILY`,
    // `TAURI_PLATFORM_VERSION`, `TAURI_PLATFORM_TYPE` and `TAURI_DEBUG`
    // env variables
    envPrefix: ['VITE_', 'TAURI_'],
    build: {
      // Tauri supports es2021
      target: ['es2021', 'chrome100', 'safari13'],
      // don't minify for debug builds
      minify: 'esbuild',
      // produce sourcemaps for debug builds
      sourcemap: 'inline',
    }
  }
})

```

Ok, now we are ready to add our Tauri app part!

### Adding Tauri

Let's add the Tauri CLI as it will help us to install the Tauri app along with our Vite app:

```bash
> pnpm add -D @tauri-apps/cli
```

Now that we've got it installed, run:
```bash
> pnpm tauri init
```

It will except you to answer a bunch of questions:
```bash
> ? What is your app name? <yourappname>
> ? What should the window title be? <you can leave it the same as your app name>
> ? Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri/tauri.conf.json" file that will be created? ../dist
> ? What is the url of your dev server? › http://localhost:5173
> ? What is your frontend dev command? › pnpm run dev
> ? What is your frontend build command? · pnpm run build
```

You should now see a folder called *src-tauri* as the root of your project. 

Then navigate to *src-tauri* directory then run these commands:
```bash
> cargo add tauri@2.0.0-alpha.4
> cargo add tauri-build@2.0.0-alpha.2 --build
> cargo install tauri-cli --version "^2.0.0-alpha"
```

Ok, we need to adapt our project file in order to launch it on mobile. Open your `Cargo.toml` file located inside *src-tauri* and add these lines:

```toml
[package]
name = "snapchat"
version = "0.0.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
edition = "2021"

[lib]
crate-type = ["staticlib", "cdylib", "rlib"]

...
```

Now go inside your *src* folder on the same level and add 2 files `lib.rs` and `mobile.rs` with those lines:

```rs
// lib.rs

use tauri::App;

#[cfg(mobile)]
mod mobile;
#[cfg(mobile)]
pub use mobile::*;

pub type SetupHook = Box<dyn FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send>;

#[derive(Default)]
pub struct AppBuilder {
  setup: Option<SetupHook>,
}

impl AppBuilder {
  pub fn new() -> Self {
    Self::default()
  }

  #[must_use]
  pub fn setup<F>(mut self, setup: F) -> Self
  where
    F: FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send + 'static,
  {
    self.setup.replace(Box::new(setup));
    self
  }

  pub fn run(self) {
    let setup = self.setup;
    tauri::Builder::default()
      .setup(move |app| {
        if let Some(setup) = setup {
          (setup)(app)?;
        }
        Ok(())
      })
      .run(tauri::generate_context!())
      .expect("error while running tauri application");
  }
}
```

---
```rs
// mobile.rs

#[tauri::mobile_entry_point]
fn main() {
  super::AppBuilder::new().run();
}
```

Then replace our `main.rs` file to use the **AppBuilder** struct:

```rs
//main.rs

#![cfg_attr(
    all(not(debug_assertions), target_os = "windows"),
    windows_subsystem = "windows"
)]

pub fn main() {
    app::AppBuilder::new().run();
}
```

Now we are ready to initiate our android project. Let's run go back to our root project and run this:
```bash
pnpm add -D @tauri-apps/cli@next @tauri-apps/api@next && pnpm tauri android init
```
With this command, the cli tool will do some configuration for us so let's sit back and wait for it to complete 🧋

✅ When the cli has finished, go to **src-tauri**, you should now see a folder called **gen** with some **android** relative files in it. It means that the tool has correctly generated an android project for you 👍.

One last thing before we run this on our device. Open `tauri.conf.json` file inside `src-tauri` and change the bundle identifier to a custom one following this pattern `com.$developeralias.$appname`. For example, for me, i've changed it into: `com.yourname.appname`. 

Ok, now let's run our app 😁, run the command: `pnpm tauri android dev [--open]`

What this command will do is trying to launch our app on android emulator and if it doesn't find one, it will open Android Studio for you. In my case, i want to run it on my real device so i'll wait the Android Studio to pop up.

---
❌ I had to change this line in the build.gradle.kts file to match my configuration:
```kts
// Change this
implementation("com.android.tools.build:gradle:7.3.1")

To this
implementation("com.android.tools.build:gradle:7.2.1")
```

⚠️ If you stumble across an error saying that *@tauri-apps/cli-darwin-x64 is missing*, then install the required dependency by `pnpm i --save @tauri-apps/cli-darwin-x64`

---

## Test


![android studio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cfzj64nmorz8jb9c7td.png)

Time to run our app! As you can see, it opened up Android Studio and detected my device perfectly. Just go on and click on the "Run app" button and wait for the app to run.

---
If the app doesn't run on the first time, try to close Android Studio and re-run the command:
```bash
> pnpm tauri android dev [--open]
```
---

![android app running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n512sbh25q87a7rcu2b0.jpg)

Yay! 🎉🎉🎉

Now try to change something inside *src/App.tsx* and save it. Changes are directly taken into account and update your app! 🤯🤩

As Tauri uses your favorite framework to load, you can use our favorite tools with it!

You can also build your app by doing this command:
```bash
> pnpm tauri android build
```

## Final words

Tauri for mobile is still in [alpha release](https://next--tauri.netlify.app/blog/2022/12/09/tauri-mobile-alpha) so i do not recommend using it on production but i think that it's already pretty cool 😎. Next time we will discuss about the interaction with Rust and mobile plugins! 😀

Let me know if you want me to do more tutorial about it! 😊

Thank you for sticking with me till the end! See y'all! 👋

<a href="https://www.buymeacoffee.com/ailifidaach" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>