- Ruby / Rails以外の開発一般
- Ruby / Rails関連
Rails: Hotwire Nativeで作るネイティブモバイルアプリ: Android編(1)セットアップ(翻訳)
Rails: Hotwire Nativeで作るネイティブモバイルアプリ: Android編(1)セットアップ(翻訳)
Hotwire NativeのiOSシリーズをずっとお読みいただいた方なら、iOS編でカスタムキーボード拡張機能を表示する方法まで学び終わったことをご存知でしょう。
今後4回の記事では、Hotwire NativeによるAndroidアプリ開発について説明します。最初はアプリのセットアップ、次にネイティブ画面の表示、コンポーネントブリッジ、最後にカスタムキーボード拡張機能に進む予定です。
🔗 背景(読み飛ばしても構いません)
読者のほとんどはHotwireについて既にひととおりご存知だと思いますが、手短に背景を説明しておきます。
Hotwireは、「Web」「iOS」「Android」を対象とするライブラリのコレクションで、サーバー側でレンダリングするHTMLをマークアップする際の人間工学を重視しています。
Hotwireの方法論は、ReactなどのSPA(シングルページアプリケーション)フレームワークがHTMLをオンザフライで生成し、JSONエンドポイントからの入力に基づいて状態の変更に「反応(react)」することが多いのとは対照的です。
Hotwireの中核にあるturbo.jsというライブラリは、ブラウザのページ全体を再読み込みする必要も、キャッシュなどの追加機能の実行も必要もなしに、ページナビゲーションを処理します。
turbo.jsのようなライブラリを利用するメリットは、SPAについて回る開発上の欠点を取り除いて、SPAのさまざまな長所を得られることです。
🔗 Railsアプリをセットアップしてみよう
Hotwire Nativeはturbo.jsと共生関係にあるので、ページナビゲーションをturbo.jsで処理しているアプリなら問題なく利用できます。
turbo.jsは任意のバックエンドフレームワークで利用可能ですが、Railsではデフォルトで付属しています。
アプリがまだない方は、さくっと作ってみましょう。本記事ではRails 7.2以降を利用することを前提としています。
rails new hotwire_native_todo
scaffoldで手早く作成を済ませましょう。
rails g scaffold Todo title:string complete:boolean
マイグレーションも実行します。
rails db:migrate
それではToDoのindexページをhomeページに設定しましょう。
config/routes.rbファイルにroot "todos#index"
を追加します。
# config/routes.rb
Rails.application.routes.draw do
resources :todos
root "todos#index"
end
最後に、アプリケーションレイアウトにsimplecssを追加してスタイルを手早く整えましょう。
<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
...
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
</head>
<body>
...
それではRailsサーバーを起動して、いよいよiOSアプリに取り掛かることにしましょう。
bin/rails s
ブラウザでlocalhost:3000
を実行すると、できたてのRailsアプリが表示されるはずです。
🔗 Androidアプリをセットアップする
🔗 Android Studioでプロジェクトを新規作成する
最初に、Android Studioがインストール済みであることを確認しましょう。
Android Studioで、File -> New Project -> Empty Views Activityを実行します(訳注: プロジェクト名は「Hotwire Example」にしておきます)。
次に、Minimum SDKを28に設定し、Finishをクリックします。
🔗 Hotwireをインストールする
Hotwireの最新バージョンを以下で調べておきます。
参考: Releases · hotwired/hotwire-native-android
Android Studioでアプリのbuild.gradle.kts
ファイルを開いて以下の依存関係を追加し、バージョン番号を上で調べたHotwireの最新バージョンに変更します。
dependencies {
implementation("dev.hotwire:core:1.1.1")
implementation("dev.hotwire:navigation-fragments:1.1.1")
}
🔗 オプションでlibs.versions.tomlを使う
このセットアップ方法が最短です。または、Androidの規約に沿う形でlibs.version.toml
ファイルを利用する方法も可能です。このファイルは、Gradleがアプリの依存関係を一元管理するのに使われます。これは、バージョン番号を含むGemfileやpackage.jsonの一部としてお考えください。
libs.versions.toml
ファイルに以下を追加して、バージョン番号を上で調べたHotwireの最新バージョンに変更します。
[versions]
...
hotwire = "1.1.1"
[libraries]
...
hotwire-core = { module = "dev.hotwire:core", version.ref = "hotwire" }
hotwire-navigation-fragments = { module = "dev.hotwire:navigation-fragments", version.ref = "hotwire" }
[plugins]
...
これで、build.gradle.kts
ファイルに以下を追加すればコード補完が効くようになるはずです。
dependencies {
implementation(libs.hotwire.core)
implementation(libs.hotwire.navigation.fragments)
...
これで、変更を同期して準備が整います。
🔗 Android ManifestでInternet permissionを有効にする
AndroidManifest.xml
ファイルで、以下を<application
の直前の行に追加します。
<uses-permission android:name="android.permission.INTERNET"/>
🔗 Android ManifestでCleartextTrafficを許可する
localhostにアクセス可能にするため、AndroidManifest.xml
ファイルで以下のようにCleartextTraffic
も有効にする必要があります。
<application
android:allowBackup="true"
+ android:usesCleartextTraffic="true"
android:dataExtractionRules="@xml/data_extraction_rules"
....
</application>
🔗 レイアウトをセットアップする
res/layout/
ディレクトリの下にあるactivity_main.xml
ファイルを開いて、以下のアイコンをクリックします。
ファイル全体を以下のコードに置き換えます。
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_nav_host"
android:name="dev.hotwire.navigation.navigator.NavigatorHost"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="false" />
🔗 Main Activityを設定する
作業もほぼ終わりに近づきました。MainActivity.kt
ファイルの内容を以下に置き換えます。
import android.os.Bundle
import dev.hotwire.navigation.activities.HotwireActivity
import dev.hotwire.navigation.navigator.NavigatorConfiguration
import com.example.hotwireexample.R
class MainActivity : HotwireActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun navigatorConfigurations() = listOf(
NavigatorConfiguration(
name = "main",
startLocation = "http://10.0.2.2:3000",
navigatorHostId = R.id.main_nav_host
)
)
}
このとき、関連するライブラリもimport
しておくこと。
訳注
初回のビルドエラーを防ぐために、この時点でFile→Sync Project with Gradle Filesと、Build→Clean ProjectおよびBuild→Rebuild Projectを実行しておくとよいでしょう。
最後に、Run→ Run 'app'をクリックして(またはCtrl + Rで)アプリをエミュレータで起動します。
🔗 まとめ
これですべての設定が完了し、準備が整いました。
ただし今のままではネイティブな感覚が足りません。次回の記事では、パス構成(path configuration)を追加することで /new
や/edit
に移動するたびにモーダルを表示できるようにする方法を解説します。
それではまた次回に。
関連記事
Rails: Hotwire Nativeで作るネイティブモバイルアプリ: iOS編(3)ブリッジコンポーネント(翻訳)
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。
従来Turbo NativeとStradaと呼ばれていたものは、現在はHotwire Nativeに統合されました。
参考: Hotwire Native: Hotwire Native is a web-first framework for building native mobile apps.