Flutterを使ったアプリを作ってみる - 基礎編

以前から、スマフォアプリ作成のプラットフォームとしてクロスプラットフォームなものがいくつか登場してきていますが、PhoneGapCordovaに始まり、React Nativeなどと変遷し、今はGoogle提供のFlutterが熱いようです。といっても、Android/iOSのネイティブ環境での開発と比較して、痒いところに手が届かないといった理由などから、結局はJava / Swift / Objective-C / Unity(C#)で作成に戻るケースもあるようです。

とはいえ、個人で複数の言語を扱って、それぞれのネイティブ環境に合わせて学習するのは正直大変。ということで、今回、Flutterで実際に開発をしてみてどこまで行けるのかまとめてみることにしました。

今回開発で使用する環境

Flutterはマルチプラットフォームであるため、Windows, Linux, macOSで開発することが可能。また、Flutter2からはデスクトップアプリの作成も可能になったようで。今回は、macOS上で作成にチャレンジしています。シェルはzshを利用しています(ターミナルから echo $SHELLで調べられます)

ウェブには1.x系の古い書き方の記事と、2.x系の新しい書き方の記事が混在しており、1.x系の書き方ではNGになりますので、学習する場合にはよく見極めてから取り組む必要があります(現在は、Version 3.0となっています)

図:日々バージョンアップしていく

開発環境の整備

M1 Macの場合の事前準備

202年5月時点では、Flutterの開発環境はRosetta2も必要のようで・・・。ターミナルからRosetta2をインストールしておきましょう。

Flutter SDKのインストール

まずは開発基盤であるFlutter本体をインストール。以下の手順でインストールします。

  1. SDK配布サイトを開き、開発するOSを選択(ChromeOSの選択肢があるのが面白い)。M1 Macの場合は、macOSを選んで、flutter_macos_arm64を選びます。
  2. Get the Flutter SDKにあるflutter_macos_2.5.1-stable.zipをクリックしてダウンロード。
  3. ZIPファイルを解凍すると、flutterというフォルダが出来る
  4. ユーザディレクトリにflutterdevというフォルダを作って、その中に3.を移動させる
  5. このフォルダに対してPATHを通す必要があるので、好きなテキストエディタを起動する
  6. 開くにて、不可視ファイルを表示にチェックを入れて、ユーザディレクトリ直下の.zshrcもしくは.bash_profileを開く
  7. 以下のような記述を追加して保存する。
  8. ターミナルを再起動して、which flutterでflutterコマンドの場所が表示されればOK
  9. ターミナルで続けて、flutter doctorを実行して完了です

図:bashの場合はこのファイルにパスを通す

図:パスが無事に通った

Flutter Desktopを利用する

Desktopの有効化

2022年2月、Flutter DesktopがStableとしてリリースされて、デスクトップアプリも作成可能になっていますが、デフォルトで無効になっているので、ターミナルから以下のコマンドを実行して有効化します。

そして、プロジェクトを作成する場合、ターゲットを指定して作ることになります。

設定が完了してる場合は以下のコマンドでmacOS(Desktop)が表示されます

macOS向けにビルドする場合には以下のコマンドで行います。

図:macOS Desktopが有効化された

Windows特有の問題

Flutter自体はマルチプラットフォームなのですが、Desktopのビルドを作成する際に、macOS上ではWindows用ビルドを構築出来ません。そのため、同一コードであったとしても、ビルドはWindows上で行う必要があり、また、Visual Studio(現在2022)が必要になるため、事前にインストールしておく必要性があります。

vcruntime140.dll等もビルドパッケージに含める必要があり、Visual Studioのディレクトリからコピーしてきてdistに含めます。

macOS特有の問題

macOSでは、アプリケーションは署名されている必要があり、そうではないアプリは実行を阻止される仕組みがあります。しかし、Flutterで開発中のビルドに於いて、そのままではネットワークアクセスやカメラ、ファイルアクセスをさせたい場合に、アプリの外側へのアクセスが遮断されてしまいます(サンドボックス内での閉じた環境になってるので、解除しデバイスへのアクセス許可を追加します)。

以下の2つのファイルに対して、作業を行います(デバッグ用とリリース用の2つに対して行います)。プロジェクト直下の以下のファイルを開きます。こちらに詳しい資料があります。

  • macos/Runner/DebugProfile.entitlements
  • macos/Runner/Release.entitlements

上記のファイルを開き、sandboxをfalseに、他のアクセスをtrueにする記述を追加します。必要な要素だけ追加しましょう。

図:編集するファイルと内容

図;flutter runして起動してみた

Android Studioのセットアップ

開発基盤はインストールできましたが、開発用のIDEがまだ準備できていません。Android向けに作成するにせよしないにせよ、IDEとしてAndroid Studioがベターなので、インストールします。

  1. Android Studioをダウンロードする
  2. 途中、説明書きが出るので最後まで読んで、チェックを入れる。IntelもしくはApple Chipのどちらかを環境に合わせて選んでクリック。
  3. DMGファイルがダウンロードされるので、マウントする
  4. アプリケーションフォルダにAndroid Studioをつまんで入れればOK
  5. Android Studioを実行すると、初回のセットアップが始まります。Nextで進めて、Standardでインストールします。
  6. Finishをクリックして、ネットからモジュールをインストールが始まります。
  7. 本体が起動したら、Pluginsをクリックして、FlutterとDartを探し、インストールをします
  8. 一旦、Android Studioを終了して再起動する
  9. New Flutter Projectと表示されたら完了です。

図:プラグインのインストールも必要

VSCodeと拡張機能

Android Studioは高機能ですが故に重たい。個別のdartファイルを編集するのであるならば、VSCodeをインストールして編集したほうが楽です。以下にVSCodeと関連する拡張機能の追加を行ってみます。

  1. VSCodeをダウンロードしてインストールしておく(Win, macOS, Linuxとクロスプラットフォームで用意されています)
  2. VSCodeを起動する
  3. 左のサイドバーを開き、拡張機能パネルを開く
  4. 検索窓からjapaneseをまず検索して日本語化の為の拡張機能(japanese language pack for visual studio code)をみつけ、installを実行する
  5. 続けて、flutter用の拡張機能として、flutterで検索し拡張機能をみつけ、installを実行する(VSCodeからAndroid Emulatorを起動出来るようになる)
  6. Dartも入れろとメッセージが出るので、Yesボタンを押します。(F5キーでデバッグが出来るようになる)

拡張機能の追加はこれで完了。

VSCode自身がターミナルを装備しており、この画面からデバッグ実行やビルドを行う事も可能です。事前に後述のAndroid EmulatorのセットアップでAVD Managerで作成しておく必要があります。

  1. 作成したプロジェクトのフォルダをVSCodeで開く
  2. 右下にNo Deviceが出てくる。クリックして、作成した仮想のAndroidを選択します。
  3. 選択するとエミュレータが起動します。
  4. ターミナルからflutter runを実行するとビルドが開始されて、apkがエミュレータに送られて起動するようになります。

図:拡張機能を追加中

図:エミュレータを起動してみた

実行環境のセットアップ

AndroidおよびiOS用にアプリを動かすためのテスト環境(エミュレータ等)をセットアップします。必要な環境だけをセットアップすれば良いでしょう。

Android Emulatorのセットアップ

まずは適当にFlutter Projectを新規作成し、エディタの画面まで進めます。エディタの画面の右上に「AVD Manager」というアイコンがあるのでここをクリックして進めます。

  1. Create Virtual Deviceをクリックする
  2. Pixelシリーズなどしか列挙されていませんが、自分のスマフォのサイズに合うものを作ってみます(例:Zenfone6
  3. New Hardware Profileをクリックする
  4. 画面サイズとエミュレータで使うRAMサイズを指定して、Finishをクリック
  5. 4.で作ったプロファイルを選んで、Nextをクリック
  6. select a system imageの項目が出てくる。Zenfone6はAndroid11なので、Rを選んでDownloadをクリック
  7. Accept -> Nextをクリックし、エミュレータがダウンロードされるまで待ちます
  8. 終わったら、Finsh -> Nextで進む
  9. AVD Nameは適当につけて、GraphicはHardwareを選択します。
  10. Finishをクリックするとセットアップ完了。▶をクリックすると、エミュレータが起動します(qemuベースのようです)。

※尚、M1 Macの場合この集団が使えないので、こちらのサイトを参考にAndroid Emulatorをインストールする必要があります。

図:カスタムプロファイルを作ってる様子

図:エミュレータを起動してみた

iOS Simulatorのセットアップ

iOS用のアプリを構築するには、macOSで且つiOS Simulatorが無ければ作ることは出来ません。これらをセットアップし、使えるようにしておきます。

  1. Mac App StoreからXCodeをインストールしておく
  2. インストールが終わったら、ターミナルを開き、以下のコマンドを実行する。パスワード要求されるので入力する。
  3. 終了したら、ターミナルとXCodeを閉じる
  4. 既にiOS Simulatorも入ってるので、Spotlightやアプリ一覧から、Simulatorと検索すれば出てきます。
  5. Android Studioから起動する場合は、真ん中あたりにあるツールバーのメニューから「iPhone 11 (Mobile)」を選択して、実行ボタン()を押すだけ。

開発環境の準備が完了したら、ターミナルからflutter doctorを実行して不備がないかチェックする機能が備わっています。不足してるものや、最新版であるかどうかなど色々チェックされます。flutter自身のアプデは、flutter upgradeで行います。

図:足りないセットアップを確認中

トラブルシューティング

ここまでで殆どのセットアップは完了していますが、flutter doctorをしてみた結果、まだ2項目NGの状態になっていました。その2つとは

  • CocoaPodsのインストール
  • Android Toolchain

以上の2項目は以下の手順で解消します。

CocoaPodsのインストール

予め、M1 MacにHomebrewがインストールされている必要があります。インストールされていたら以下の手順でインストールするだけです。

  1. ターミナルを起動する
  2. brew install cocoapodsでインストールする

これだけです。

Android Toolchainの問題解消

Android Toolchainとは、「Android SDK Command-line Tools」の事であり、Android Studioだけでは駄目で、別途インストールしてあげる必要があるようです。

  1. Android Studioを起動する
  2. SDK Managerを開く
  3. Android SDKの右パネルの「SDK Tools」を開く
  4. Android SDK Command-line Tools Lastestにチェックを入れて、Applyをクリック
  5. ダウンロードされてインストールされる
  6. 続けてターミナルを起動して以下のコマンドを実行し、全てに「y」で回答する

Android Studioを閉じて、再度Flutter Doctorを実行すれば全ての問題が解消されているはずです。

図:Command Line Toolsが必要

図:無事全部クリアした

Androidのビルドが失敗する

Flutterプロジェクトを作成して、何も足さず引かずでいきなりEmulatorを起動してデバッグ実行してみたところ、色々とエラーが発生してエミュレータ内で実行も出来ずだったので調べて見た。

Plugin with id ‘com.android.application’ not found.

いきなり出たエラーがこのエラー。app/build.gradleのファイルの24行目がオカシイということなのだけれど、この問題の原因はandroid/gradle/wrapper/gradle-wrapper.propertiesというファイル。このファイルのdistributionUrlにあるgradleのバージョンが問題のようで、デフォルトで記載のあったgradle-7.4-all.zipではなく、gradle-7.2-all.zipに変更してみた所、問題が出なくなりました。

どうやら、build.gradleのdependenciesにある「com.android.tools.build:gradle」のバージョンに合わせてあげる必要があるようです。しかし、7.2のgradleに変更した所問題なく動作するようになりました。

図:厄介な問題の1つ

Runtime JAR files in the classpath should have the same version

続けて、もう一度ビルドを実行してみた所、色々ダウンロードが始まりうまくいくか?と思ったら出たエラーがコレ。どうやら、Flutterインストール時に付いてくるJDKのバージョンに誤りがあるようで、android/app/build.gradleのファイルにあるdependenciesの内容を変更すると動作する。

デフォルトだと、「org.jetbrains.kotlin:kotlin-stdlib-jdk7」になってるので、これをjdk8に書き換える

図:無事にビルドできるようになった

後から対応プラットフォームを追加する

プロジェクト作成時に特定プラットフォーム向けだけにプロジェクトを作成した後に、やはり対応プラットフォームを追加したい。そんな時どうしたらよいかといったら、既存のプラットフォーム向けのフォルダに対して、flutter create .で再度作成すればOK。特定プラットフォームだけを追加したい場合には、以下のようなコマンドを実行すると上書きで作成してくれる。

  1. ターミナルを起動する
  2. 対象のプロジェクトフォルダまで移動する
  3. 以下のようなコマンドを実行して、特定プラットフォームを追加する

図:エミュレータでも無事に起動出来た

まずは作ってみる

FlutterはCordovaなどと違い、HTMLで記述したりするのではなくDart言語ウィジェットと呼ばれるパーツの組み合わせで画面をデザインし処理を実装します。よって、複雑な事を実装したいであったり、トリッキーな画面を装備したいとなるとそれは「KotlinSwiftなどのネイティブ言語でやったほうが良い」という結論になります。

標準的且つ外部ライブラリで十分なGUIと処理を実現出来るプロジェクトならばFlutterで実装し、ゲームなどはネイティブか?Unityを使うことになるでしょう。

一番最初に大きな壁になるのは、やはり独特なUIの構築。Dart言語の習得よりもこれが一番苦労することになると思います。

プロジェクトを新規生成する

なにわともあれ、まずプロジェクトを新規生成しなければ始まりません。ターミナルから以下のコマンドで新規に作成します。どんな構造でファイルが生成されるかをまず学びます。今回は、calcmanというプロジェクトを生成してみました。

生成されたファイルを見てみるとなにやら沢山出来ています。この中でまずは、最初の一歩で編集するファイルは、libフォルダ内にあるmain.dartというファイルになります。ここに処理やウィジェットの追記を行っていきます。

図:プロジェクト生成中

図:生成されたファイル群

ファイルを編集する

lib/main.dartファイルをVS Codeなどで開いてみます。Android Studioで開く場合は、Open -> calcmanのフォルダを指定で開くだけ。VSCodeでもプロジェクトフォルダを開くと、エミュレータでデバッグが可能になります。

今回は公式サイトにあるコードでmain.dartファイルの中身を書き換えて保存しました。

図:個人的にはVSCodeのほうが楽

デバッグの実行

ターミナルを開いて、flutter runを実行するとビルドが始まりアプリが起動します。エミュレータセットアップしていない場合は、Chromeが起動してアプリが表示される仕組みです。なお、Flutterにはホットリロードという機能があり、起動後にCommand+Sキー(Ctrl+S)を実行すると、書き換えた内容が直ちに反映するという高速デバッグ機能が備わっています。

※VSCodeの場合は、デバッグ開始⇒実行後にrキーを押すとホットリロードされます(但し、読み込まれたクラスは再読み込みされないので、その場合はホットリスタートすると良い。↑⌘F5キーを実行。)

また、Node.jsのcosole.logのように変数の中身をトレースしたい場合には、debugPrint(変数名)にて、出力する事が可能で、内容はターミナル内やChromeのデベロッパーツールのconsole内にも表示されるようになります。

図:アプリを実行中

図:変数のデバッグ

外部パッケージの追加

Flutterアプリに機能を追加するにあたって、自前でゴリゴリ作るのも良いのですが、Node.jsのnpmのように簡単にライブラリを追加して簡単に使えるようにする機能がFlutterにも備わっています。追加手順は以下の通り

  1. Flutter Packagesのサイトを開く
  2. 使いたいパッケージを検索。今回は、Flutterでfont awesomeを使う為の「font_awesome_flutter」を探します。
  3. installingタブを開く
  4. ターミナルを開き、プロジェクトのフォルダのところまで移動しておく
  5. flutter pub add font_awesome_flutter」を実行する
  6. Node.jsで言う所のpackage.jsonにあたるpubspec.yamlファイルに、パッケージの記述が追加される(font_awesome_flutter: ^9.1.0という記述がdependenciesに追加されてる)
  7. main.dartファイル冒頭に、「import 'package:font_awesome_flutter/font_awesome_flutter.dart';」の記述を追加すると、そのプロジェクトファイルでパッケージが使えるようになる
  8. 以下のコードをbodyセクションの中に以下のような記述を追加する。アイコンギャラリーはこちらから検索可能。FontAwesomeIcons.androidで、指定のfontawesomeのアイコンを表示可能です。
  9. ターミナルからflutter runで起動してみる

図:アイコン表示に成功した

ステートフルウィジェットとボタンの追加

冒頭の公式サイトのサンプルコードではメイン画面の部品であるMyAppはStatelessWidgetとして記述されています。もう一つ、StatefulWidgetというものも存在します。この違いは、前者が静的なウィジェット、後者が動的なウィジェットでレンダリング後に自身の内容を変更できない/出来るの違いになります。通常はあまり静的な状態でアプリを作るというケースは少ないと思われるので、サンプルのコードをStatefulWidgetに変更し、ボタンを配置、関数を呼び出し反映するといったものに変えてみます。

  • Dartではvar hogeのように型推論の書き方も出来ますが、通常はString hogeのように型指定を行います
  • 型指定の場合、指定以外の値を入れることは出来ません。
  • class内に関数をvoidで用意した場合には、class内で定義した変数にそのままアクセス可能
  • 文字の結合の場合は数値は一旦.toStringで行わないと、+で結合は出来ない。
  • 親のStatefulWidgetから子のclassをcreateStateで呼び出し、Widget buildの内容返しています。
  • 今回のケースでは、ボタンをタップする毎にボタン内のテキストにタップした回数がカウントアップされていきます。
  • ボタンはElevatedButtonを利用(古い記事だとRaisedButtonになっていたりするが、現在は使えない)
  • Body以下に、テキスト表示のcontainerとrowを配置、rowの中にchildrenとしてボタンを配置しています。
  • 呼び出された関数内からclass内の変数を変更する場合は、setState()にて変更を行います。

図:ボタンクリックでカウントアップするアプリ

テーマやスタイルの適用

テキストなどに対して個別に色やフォントスタイル、またアプリ全体のテーマ設定でカラーリングの変更が出来ます。ダークテーマなどを簡単に実装できるようになってるのが今風です。

  • theme:ThemeDataにて、primarySwatchの色を指定するとアプリのテーマカラーを変更可能です。
  • 色の指定はこちらのColor Classから選ぶ事が可能
  • theme: ThemeData.dark()を指定するとダークモードになります。

図:紫をテーマカラーにしてみた

VSCodeで実行してみる

VSCodeで書けるようにすでに準備をしているので、試しにとあるGithubにあるプロジェクトを動かしてみようと思います。今回は、Puppeteer in dartと呼ばれる、FlutterでPuppeteerを動かすという面白いプロジェクトを動かしてみます。

  1. Githubのページの緑色のボタンである「Code」をクリックして、Download Zipをクリックする
  2. 解凍したら、適当な場所に移動させる
  3. VSCodeを起動して、2.のフォルダを開く
  4. 足りないライブラリについてインストールするか?聞いてくるので、許可してインストールする
  5. F5キーを押すと、.vscodeの中のlaunch.jsonが開かれるので、以下のようにprogramの項目を追記してあげる

    exampleの中にあるscreenshot_page.dartを今回は実行してみます。中にあるpage.gotoの場所をGoogleのトップページに書き換えてあります。
  6. もう一度F5を実行すると、VSCode上でデバッグが実行されて、Dartのプログラムが動きます。
  7. 今回はPuppeteerはHeadlessで動いてるのでChromeは表示されず、完了すると青いラインでVSCodeの下の方に完了した旨が表示され、exampleフォルダの直下にpngの画像がスクショとして生成されています。

図:VSCodeでプログラムを実行出来る

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)