7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

ElixirDesktopでスマホアプリを作る - Phoenix1.7のアプリを起動

Last updated at Posted at 2023-07-14

こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はElixirDesktop + Phoenix1.7のスマホアプリをWindows11 + WSL2で動かす手順をまとめたいと思います。


なお、本記事は2023/7/13開催ElixirMobile#3:DBも内蔵したElixirDesktopスマホアプリ開発ハンズオンのイベントレポート(前半)を兼ねています。

------ハンズオンの様子(前半)はこちらから------

↓ ~27:03までが本記事のハンズオン動画です。


■「ElixirDesktopでスマホアプリを作る」シリーズの目次
Windows11+WSL2に環境構築
|> ②Phoenix1.7のアプリを起動
|> ③LiveViewを使用してCRUDの機能を実装する
|> ④Android実機に転送する(Google Drive経由)

目的

こちらの記事をWindows11 + WSL2の環境で動かします。

実行環境

Windows 11 + WSL2 + Ubuntu 22.04
Elixir v1.14.3
Erlang v25.0.4
Phoenix v1.7.3

前提条件

Elixirのインストール

以下のいずれかが未実施の場合は前回の記事を参照して環境構築を行ってください。

  • Android Studioのインストール
  • NDK(※Native Development Kitの略、Android で C や C++ のコードを使用できるようにするツールセット)のインストール
  • git、npm、asdf のインストール
  • asdfを使用してのErlangおよびElixirのインストールと設定(※バージョン指定があります)1

Phoenixのインストール

最新のPhoenixをインストールします。
(私は既にインストール済のためスキップしました)

shell
mix archive.install hex phx_new

SQLite3のインストール

apt経由でSQLite3をインストールします。2

shell
sudo apt install sqlite3

プロジェクトの作成

DBはsqlite3を使うので --database sqlite3のオプションをつけます。
また、Phoenixのプロジェクトとandroid-studioのプロジェクトの2つが必要なので、両方のプロジェクトをいれるディレクトリを作成します。

shell
mkdir todo_root
cd todo_root
mix phx.new todo_app --database sqlite3
cd todo_app
mix ecto.create #todo_app_dev.dbが作成される

ライブラリの追加

todo_app/mix.exs
  defp deps do
    [
      ...
+      {:exqlite, github: "elixir-desktop/exqlite", override: true},
+      {:desktop, "~> 1.5"},
+      {:wx, "~> 1.1", hex: :bridge, targets: [:android, :ios]}
    ]
  end
  • exqliteとは、ElixirDesktopからSqlite3を操作するライブラリ
  • desktopとは、ElixirDesktopフレームワーク本体
  • wxとは、ElixirDesktopをスマートフォン上で動かすためのライブラリ

追加後、以下を実行します。

todo_app
mix deps.get

config修正

todo_app/config/config.exs
 config :todo_app, TodoAppWeb.Endpoint,
-  url: [host: "localhost"],
+  http: [ip: {127, 0, 0, 1}, port: 10_000 + :rand.uniform(45_000)],
   render_errors: [
     formats: [html: TodoAppWeb.ErrorHTML, json: TodoAppWeb.ErrorJSON],
     layout: false
   ],
   pubsub_server: TodoApp.PubSub,
-  live_view: [signing_salt: "J82JhPeQ"]
+  live_view: [signing_salt: "J82JhPeQ"],
+  secret_key_base: :crypto.strong_rand_bytes(32),
+  server: true

※signing_saltの値は人によって異なります。

  • secret_key_baseとは、secureな文字列を作る際のベースになるもの。
  • server: trueとは、アプリケーションが起動しているサーバーのIPアドレス + ポート番号への外部からのアクセスを受け付けられるようになる設定。3

runtime.exsの無効化

アプリの実行時にtodo_app/config/runtime.exsがあるとエラーになるそうです。
よって、runtime_disable.exsにリネームしておきます。

Endpoint設定

EndpointのモジュールをPhoenixからDesktopに変更します。
ElixirDesktopではcookieでのセッション管理を使えないのでetsに変更します。

todo_app/lib/todo_app_web/endpoint.ex
 defmodule TodoAppWeb.Endpoint do
-  use Phoenix.Endpoint, otp_app: :todo_app
+  use Desktop.Endpoint, otp_app: :todo_app

   @session_options [
-    store: :cookie,
+    store: :ets,
     key: "_todo_app_key",
-    signing_salt: "GvxD48aX",
-    same_site: "Lax"
+    table: :session
   ]

アプリケーション起動時の設定

todo_app.exにどのような手順でPhoenixアプリケーションを起動していくかの設定をします。
todo_app.exにはデフォルトではドキュメントしか書かれていないので、以下を追加します。

todo_app/lib/todo_app.ex
 defmodule TodoApp do
+  use Application

+  def config_dir() do
+    Path.join([Desktop.OS.home(), ".config", "todo_app"])
+  end

+  @app Mix.Project.config()[:app]
+  def start(:normal, []) do 
+    # ~/.config/todo_appフォルダを作成する。その中に設定ファイルを放り込んでいく
+    File.mkdir_p!(config_dir())

+    # DBの場所を指定
+    Application.put_env(:todo_app, TodoApp.Repo,
+      database: Path.join(config_dir(), "/database.sq3")
+    )

+    # session用のETS(インメモリDB)を起動
+    :session = :ets.new(:session, [:named_table, :public, read_concurrency: true])

+    children = [
+      TodoApp.Repo,
+      {Phoenix.PubSub, name: TodoApp.PubSub},
+      TodoAppWeb.Endpoint
+    ]

+   opts = [strategy: :one_for_one, name: TodoApp.Supervisor]

+    # Phoenixのsuperviserをメインとして起動
+    {:ok, sup} = Supervisor.start_link(children, opts)

+    # DBの初期化とマイグレーション実行
+    TodoApp.Repo.initialize()

+    # phoenixサーバーが起動中のポート番号を取得
+    port = :ranch.get_port(TodoAppWeb.Endpoint.HTTP)

+    # ElixirDesktopのsuperviserを子プロセスとして起動
+    {:ok, _} =
+      Supervisor.start_child(sup, {
+        Desktop.Window,
+        [
+          app: @app,
+          id: TodoAppWindow,
+          title: "TodoApp",
+          size: {400, 800},
+          url: "http://localhost:#{port}"
+        ]
+      })
+  end

+  def config_change(changed, _new, removed) do
+    TodoAppWeb.Endpoint.config_change(changed, removed)
+    :ok
+  end
end
  • Desktop.OS.home()はユーザーのホームディレクトリを返す関数4
  • superviserとは、アプリが落ちたときに自動的にプロセスキルして再起動してくれるもの。堅牢なシステムを作る際に有用。

repo.exの変更

todo_app.exから呼び出される関数の設定をします。
(ひとまず空の関数を置いておきます)

todo_app/lib/todo_app/repo.ex
defmodule TodoApp.Repo do
  ...
+  def initialize() do
+  end
end

mix.exsの変更

mix.exsで呼び出される起動時の設定を変更します。
# アプリケーション起動時の設定 で設定したtodo_app.exに差し替えます。

todo_app/mix.exs
  def application do
    [
-      mod: {TodoApp.Application, []},
+      mod: {TodoApp, []},
      extra_applications: [:logger, :runtime_tools]
    ]
  end

以上がPhonenixプロジェクトの設定です。

androidでの起動

android-example-appのリポジトリをクローン

shell
cd ..
git clone git@github.com:elixir-desktop/android-example-app.git

run_mixの変更

run_mix5内で今回使用しないスクリプトをコメントアウトします。
使用するプロジェクトを先ほど作成したtodo_appに切り替えます。

android-example-app/app/run_mix
#!/bin/bash
set -e

BASE=`pwd`
APP_FILE="$BASE/src/main/assets/app.zip"
export MIX_ENV=prod
export MIX_TARGET=android

- if [ ! -d "elixir-app" ]; then
-   git clone https://github.com/elixir-desktop/desktop-example-app.git elixir-app
- fi

- # using the right runtime versions
- if [ ! -f "elixir-app/.tool-versions" ]; then
-   cp .tool-versions elixir-app/
- fi

- cd elixir-app
+ cd ../../todo_app

if [ ! -d "deps/desktop" ]; then
  mix local.hex --force
  mix local.rebar
  mix deps.get
fi

- if [ ! -d "assets/node_modules" ]; then
-   cd assets && npm i && cd ..
- fi

if [ -f "$APP_FILE" ]; then
  rm "$APP_FILE"
fi

mix assets.deploy && \
  mix release --overwrite && \
  cd "_build/${MIX_TARGET}_${MIX_ENV}/rel/todo_app" && \
  zip -9r "$APP_FILE" lib/ releases/ --exclude "*.so"

run_mixの実行

先にrun_mixを単体で走らせて、リリースビルドを作成しておきます。

shell
./run_mix

run_mixをブランクにする

run_mixをそのままにしてAndroid StudioのRunボタン(Android Studioの画面右上にある、緑色の▷ボタン)を押すと、再びビルドが走ってしまいます。
現時点ではrun_mixを実行済みでリリースビルドが出来上がり済のため、run_mixはもう使用しません。
よって、run_mixは別名でバックアップとして取っておき、run_mixそのものはブランクにします。

shell
cp run_mix run_mix_build

image.png

Android StudioでRunする

Android Studioを起動します。

shell
~/android-studio/bin/studio.sh

run_mixとrun_mix_buildがあることを確認してファイルを開きます。
image.png

Android Studioの画面右上にある、緑色の▷ボタンがRunボタンです。
これを押下すると、先ほど作成したリリースビルドを読み込んで、エミュレータ上でアプリが起動します。
run_mixがブランクになっていることを確認して、Runボタンを押下します。

image.png

Phoenix1.7が起動しました!(^▽^)/
image.png

次の記事へ

~Elixirの国のご案内~

↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。

We Are The Alchemists, my friends!:bouquet:6
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。7

  1. 2023/7/12時点ではErlang26系では動かなかったとのことです。https://qiita.com/the_haigo/items/17a89b5038a7f337b102#elixir%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

  2. sqlite3の導入。参考にさせていただきました。 https://qiita.com/t-yamanashi/items/ef4c5bcab4a130105760

  3. 外部とはローカルホスト(同一マシン)以外を指す。

  4. https://github.com/elixir-desktop/desktop/blob/5927dc42d97305c43cad523b905153b687434219/lib/desktop/os.ex#L21

  5. run_mixとは
    ダウンロードしたリポジトリ内のrun_mixはビルドスクリプトといって、
    1.GitHubからexampleをcloneしてくる
    2.ライブラリのインストール等を行う
    3.リリース(prod環境ビルド)に必要な処理を行う
    4.Zipで圧縮
    5.Android側が読み込むようにしてある場所にコピー
    以上の処理をまとめて走らせてくれるシェルスクリプトのこと。
    https://qiita.com/Alicesky2127/items/5f9a1c6496b1c083720f#run_mix%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B
    ※なお、今回は1.についてはコメントアウトして実施しないようにしている。

  6. @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。

  7. @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中!

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?