AndroidでSlintを動かそう

# はじめに
普段はQtの話ばかりな底辺系フリーランスのhermit4です。ごきげんよう。
あまりに長く同じことをやりすぎてつまらなくなったので、最近はRustとSlintのお勉強を始めています。

そして、このたび合同会社シグナルスロット様のご厚意で、次週11/20から11/22までみなとみらいで行われるEdge Tech+2024でのSlintの展示と紹介をお手伝いさせていただけることになりました。会場へお越しになる方はぜひ遊びにきてください。

さて、そんな展示のための知識をつけるべく色々と試していたのですが、Qiitaの記事にして良いよということでしたので記事にしておきます。

## Slintとは
SlintはドイツのSixtyFPS GmbH社の作った宣言型UI言語・フレームワークです。Rustで開発されており、Rustはもちろん、C++, Python, JavaScriptなどから呼び出しが可能です。組込向けにベアメタルでRaspberry pi picoの上ですら動かせますが、そのほかに対応するプラットフォームとしてLinux, MacOS, Windowsはもちろん、AndroidやZephyr、マイナーどころだとRedoxでも利用可能とされています。 

簡単なチュートリアルは @task_jp さんが書いた「[GUI フレームワーク Slint の紹介](https://qiita.com/task_jp/items/5e76f66366673d46afcd)」をご確認ください。

## なんでいきなりAndroidか

元日本Androidの会で活動していた人で、勉強会やOSCでQtもAndroidで動きますとか宣伝してた人としては、SlintもAndroidで動きますという宣伝をしないわけにはいきません。

というわけで、展示会でそれっぽくタブレットで動くものを展示するためにもAndroidで動かしてみました。

# さっそくやってみよう
## 開発環境
今回は個人的な趣味でKUbuntu 24.04で構築しました。ただ、Ubuntu 24.04なら同じ手順で行けるはずです。
なお、開発環境はQEMUを動かす関係でPC上に直接構築したのですが、この手順書はVM上で手順を再検証しながら記載しています。

ただ、VMを動かした微妙に古いmacOS+Fusion13だと仮想化機能を有効にしてもQEMUの起動に失敗しまして、完全な検証はできていません。動かなかったらコメントください。

## 手順
### 必要なパッケージのインストール

今回はAndroid Studioを入れたりのGUI的な作業を割愛してコマンドラインで行きます。え、そんなマイナー路線な作業するなって？やだなー、メジャー路線を走る人はSlintやらな・・・げふん。なんでもありません。

```bash: 
sudo apt install google-android-cmdline-tools-13.0-installer curl adb cmake lldb ninja-build openjdk-11-jdk
```

### Android周りを整える
```bash:
sudo sdkmanager "emulator" "system-images;android-35;google_atd;x86_64" "ndk-bundle" "ndk;27.2.12479018" "platforms;android-30"
export PATH=$PATH:/usr/lib/android-sdk/emulator
avdmanager create avd -n testemu -k "system-images;android-35;google_atd;x86_64" -d "pixel_tablet"
emulator -avd testemu
```

これでエミュレータが起動できるはずなのですが、不足があったらごめんなさい。

### Rust環境を整える

```bash:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. ＄HOME/.cargo/env
rustup target add x86_64-linux-android aarch64-linux-android x86_64-linux-android
cargo install cargo-apk
```

### まずはHello Worldを試す
```bash:
cargo new hello --lib
cd hello
```

中身はさっくり書き換えます。

```toml: Cargo.toml
[package]
name = "hello"
version = "0.1.0"
edition = "2021"

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

[dependencies]
android-activity = "0.6.0"
slint = { version = "1.8.0", features = ["backend-android-activity-06", "i-slint-backend-android-activity"] }

[build-dependencies]
slint-build = "1.8.0"
```

```Rust:src/lib.rs
slint::slint! {
    export component AppWindow inherits Window {
        Text {
            text: "Slint & Android";
        }
    }
}

#[no_mangle]
fn android_main(app: slint::android::AndroidApp) {
    slint::android::init(app).unwrap();
    AppWindow::new().unwrap().run().unwrap();
}
```

### 起動
```bash:
export ANDROID_HOME=/lib/android-sdk/
export ANDROID_NDK_ROOT=/lib/android-sdk/ndk/27.2.12479018/
cargo apk run --target x86_64-linux-android --lib
```

で、エミュレータに流せたはずです。リリース用のAPK作成をするならもっと色々やらないといけないことは多いはずですが、デモ用に開発者モードでデバイスに入れるだけならここだけでいけます。いや、手順にまとめるとすごく簡単だったのですが、当初はAndroid Studioがすっかり変わっていて浦島太郎で手間取ったりしました。ははは・・・歳は取りたくないものです。

最初はRustをNDKで動かす古い記事をみて、NDKでさらっとRustライブラリを作ってJNI経由で呼び出す方法から学習しようと右往左往して調べはじめたのでやたら遠回りしましたが・・・いつの間にやらすごく簡単な方法ができていて、Slint動かすだけならすごく簡単でした。

重要なのは以下のクレートです。

```:
android-activity = "0.6.0"
```

このクレートが、android_mainを呼び出してくれます。あとはslint側の機能との合わせ技でこれだけでSlintで書いたUIがAndroid上に出せます。

## デモ準備
展示会では個人所有のPixel Tabletを持ち込んでAndroidで動いているSlintを展示します。

```:/etc/udev/rules.d/50-android.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="18d1", GROUP="plugdev", SYMLINK+="android%n"
```

```bash:
git clone https://github.com/slint-ui/slint.git
cd slint
cargo apk build -p energy-monitor --target aarch64-linux-android --lib
```

これで、SlintのサンプルがPixel Tabletで動きます。いや、簡単ですね。

# まとめ
駆け足でしたが、Slintで作られたアプリケーションをAndroid端末上で動かすための環境構築と手順を紹介してみました。まぁ、大雑把なやってみた系記事ですけど、試してみようという方のお役に立つなり、AIさんの糧になるなりすれば、Slintを使う裾野がひろがるかなということで公開しておきます。

自分でやるのは面倒だけど、動いているのはみてみたいという方は、ぜひEdgeTech+2024会場BT-12のシグナルスロットブースへお越しください。お待ちしてます。