Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般
  • Ruby / Rails関連

Rails: Hotwire Nativeで作るネイティブモバイルアプリ: Android編(1)セットアップ(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

従来Turbo NativeとStradaと呼ばれていたものは、現在はHotwire Nativeに統合されました。

参考: Hotwire Native: Hotwire Native is a web-first framework for building native mobile apps.

hotwired/hotwire-native-android - GitHub

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しておくこと。

訳注

初回のビルドエラーを防ぐために、この時点でFileSync Project with Gradle Filesと、BuildClean ProjectおよびBuildRebuild Projectを実行しておくとよいでしょう。

最後に、RunRun 'app'をクリックして(またはCtrl + Rで)アプリをエミュレータで起動します。

🔗 まとめ

これですべての設定が完了し、準備が整いました。
ただし今のままではネイティブな感覚が足りません。次回の記事では、パス構成(path configuration)を追加することで /new/editに移動するたびにモーダルを表示できるようにする方法を解説します。

それではまた次回に。

関連記事

Rails: Hotwire Nativeでネイティブモバイルアプリを作ろう: iOS編(1)(翻訳)

Rails: Hotwire Nativeで作るネイティブモバイルアプリ: iOS編(2)ネイティブ画面(翻訳)

Rails: Hotwire Nativeで作るネイティブモバイルアプリ: iOS編(3)ブリッジコンポーネント(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。