概要
前回の記事1では Servo を Linux 上で動作させましたが、Android 向けの開発環境について書いてみます。
Android 向けビルドでは、apk の他にブラウザのコアをライブラリとして纏めた aar を生成します。本記事では、aar を使ってAndroid のプロジェクトを作成する方法についても説明します。
環境・バージョン
- Ubuntu 22.04 (x64)
- Android 12 タブレット (arm64)
- Servo v0.0.1
Servo とは
https://servo.org/about/
Servo aims to provide an independent, modular, embeddable web rendering engine, allowing developers to deliver content and applications using web standards.
Mozilla によって立ち上げられたプロジェクト。現在は Linux Foundation Europe の下にあります。クロスプラットフォームで再利用可能な Web コンポーネントを目指しています。
詳細は前回の記事1や公式サイトを見てください。
Android版でも input 要素選択時に仮想キーボードが出ない、メディアの再生が不完全、ServoView を複数配置出来ないなど、フルブラウザとしては機能が不足していますが、基本機能は十分に動きます。
開発
基本的なビルド方法
公式ドキュメントにかかれている通り、Android SDK の指定が必要なことを除けば Linux 版と同様のコマンドで apk が作れます。
もちろん、 adb で端末へインストールできます。
export ANDROID_SDK_ROOT=$HOME/Android/Sdk
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/android-ndk-r28c
./mach build --android --media-stack dummy
adb install ./target/android/aarch64-linux-android/release/servoapp.apk
出力先ディレクトリを確認してみます。apk 以外に aar が出来ています。aar はライブラリで、後ほど使ってみます。ネイティブコードである Shared Object はほぼ 1 つに纏められています2。
$ tree -sh ./target/android/aarch64-linux-android/release/
[4.0K] ./target/android/aarch64-linux-android/release/
├── [4.0K] jniLibs
│ └── [4.0K] arm64-v8a
│ ├── [8.8M] libc++_shared.so
│ └── [128M] libservoshell.so
├── [146M] servoapp.apk
└── [ 49M] servoview.aar
2 directories, 4 files
Android Studio で開発する
現在の Servo は support/android/apk に、ビルド時に使用される Android のプロジェクトディレクトリがあります。
このディレクトリは Android Studio で直接開くことができます。libservoshell.so は Android Studio 環境ではビルドされないので、Rust コードを書き換えたら都度 ./mach ビルドを実行する必要があります。
プロジェクトは以下のモジュールで構成されます
-
buildSrc/: ビルド時に実行される -
servoapp/: メインアプリケーション -
servoview/: 移植層モジュール
ビルド時に生成されていた servoview.aar は、servoview/ をライブラリ化したもので、libservoshell.so や JNI などが含まれています。
Servo リポジトリから独立したプロジェクトで servoview.aar を使う
ビルドした servoview.aar を使用するプロジェクトを作成してみます。
1から作っても良いですが、記事を短くするため以下の方針でコードを再利用することにします。
- Servo リポジトリ内のディレクトリをコピーする
- モジュールを aar に置き換える
- Servo リポジトリ(旧リポジトリルートディレクトリ)への依存を取り除く
Servo 内のディレクトリをコピーする
ほぼそのまま動く Android Studio プロジェクトがリポジトリに含まれるため、コピーするだけで 9 割完成です。
cp -r support/android/apk $HOME/work/servo-work/
モジュールを aar に置き換える
servoview/ を servoview.aar に置き換える仕組みも既に用意されています。
user.properties に servoViewLocal 属性を定義すると、servoview-local/ モジュールが servoview/ モジュールの代わりになり、以降その aar を使うようになります。
cp ./target/android/aarch64-linux-android/release/servoview.aar $HOME/work/servo-work/
cd $HOME/work/servo-work/
echo 'servoViewLocal=./servoview.aar' > user.properties
servoview.aar の作成に関連するディレクトリを削除できるようになったので、これらを削除します。
rm -rf jni servoview obj
Servo リポジトリディレクトリへの依存を取り除く
ライブラリの取り込み、apk などの成果物のコピーのために、Android Studio プロジェクト外へアクセスするコードがあります。 servoview はビルド済みなのでライブラリの取り込みは不要、apk などの成果物のコピーも不要なので、これらは削除できます。
// buildSrc/src/main/kotlin/Interop.kt
fun Project.getTargetDir(debug: Boolean, arch: String): String {
val basePath = project.rootDir.parentFile.parentFile.parentFile.absolutePath
return basePath + "/target/android/" + getSubTargetDir(debug, arch)
}
fun Project.getNativeTargetDir(debug: Boolean, arch: String): String {
val basePath = project.rootDir.parentFile.parentFile.parentFile.absolutePath
return basePath + "/target/" + getSubTargetDir(debug, arch)
}
apk のコピーを行うビルドタスクが project.afterEvaluate で定義されているので //servoapp/build.gradle.kts から削除します。
コードブロック折りたたみ
--- a/servoapp/build.gradle.kts
+++ b/servoapp/build.gradle.kts
@@ -136,30 +136,6 @@ android {
}
}
}
-
- project.afterEvaluate {
- android.applicationVariants.forEach { variant ->
- val pattern = Pattern.compile("^[\\w\\d]+([A-Z][\\w\\d]+)(Debug|Release)")
- val matcher = pattern.matcher(variant.name)
- if (!matcher.find()) {
- throw GradleException("Invalid variant name for output: " + variant.name)
- }
- val arch = matcher.group(1)
- val debug = variant.name.contains("Debug")
- val finalFolder = getTargetDir(debug, arch)
- val finalFile = File(finalFolder, "servoapp.apk")
- variant.outputs.forEach { output ->
- val copyAndRenameAPKTask =
- project.task<Copy>("copyAndRename${variant.name.capitalize()}APK") {
- from(output.outputFile.parent)
- into(finalFolder)
- include(output.outputFile.name)
- rename(output.outputFile.name, finalFile.name)
- }
- variant.assembleProvider.get().finalizedBy(copyAndRenameAPKTask)
- }
- }
- }
}
dependencies {
これで Servo ライブラリと単純なサンプルを含むだけのプロジェクトが出来ました。
まとめ
- ビルド時に apk 以外にも aar が生成される
- Servo のアプリケーション周りの実装は build.gradle.kts のビルド構成で構築されている
- Servo を含む aar を組み込んだ Android プロジェクトを最小限の手数で作成する
普通は WebView で十分だと思いますが、変わったことをやりたい時はぜひ
-
なんかファイルサイズ大きいですね… Chromium の ContentShell と大差ないサイズです。 ↩

