Dartでネイティブモバイルアプリ開発

# Dartでネイティブモバイルアプリ開発が可能になる？！

はい、ついにこの時が来ました。

そう。

「Flutter」です。

# Flutterとは

Flutterは、Googleが開発しているモバイルアプリケーション開発のためのツールやフレームワーク整備の新プロジェクトです。

使用されるプログラミング言語はDartになります。

- [Flutter 公式サイト](http://flutter.io/)
- [Github flutter/flutter](https://github.com/flutter/flutter)

Flutterは、公式サイトでは以下のように説明されています。

> Flutter is a new project to help developers build high-performance, high-fidelity, mobile apps for iOS and Android from a single codebase.

「Flutterは、アプリ開発者が1つのソースコードでiOS, Android向けのモバイルアプリケーションを、忠実に、高パフォーマンスに開発する補助をする新プロジェクトです」

そして、以下の様な説明もあります。

> Flutter is an early-stage open-source project. We are still missing core features like accessibility, text input, localization, and more. However, you can build demos and examples today. 

「Flutterは初期段階のオープンソースプロジェクトです。まだ、アクセシビリティ、テキスト入力、ローカライズ、などのようなコア機能がありません。ただし、デモやサンプルをビルドすることができます」

なので、まだ実務レベルの開発での使用は時期尚早かと思います。


# DartはWebブラウザ向けじゃなかったの？

Flutterでは、ネイティブアプリにDartVMを載せる形でアプリが動きます。

ですので、Dartと言えど、Webフロントエンドの技術はFlutterでは使われず、FlutterのAPIを通じてアプリ開発を行うことになります。

Webフロントエンド技術を用いたものに比べて、低レイテンシ、ハイパフォーマンスなアプリを開発することができます。


# アプリの作成を試してみる

Flutter公式サイトの [Getting Started with Flutter](http://flutter.io/getting-started/) に従って、アプリの作成を試してみます。

Dartはすでにインストール済みで、dartコマンドにパスが通っている前提で説明を進めます。

筆者は、以下の環境で作業を進めます。

```bash
% dart --version
Dart VM version: 1.12.1 (Tue Sep  8 04:10:39 2015) on "macos_x64"
```

# Flutterをインストール

まずは、Flutterをインストールします。

```bash
% cd <お好きなディレクトリ>
% git clone https://github.com/flutter/flutter.git -b alpha
```

FlutterのGithubプロジェクトからalphaブランチを持ってきます。

このインストール方法は、将来的にもっと楽になるのではないかと思います。

Flutterのアップグレードをする場合は、git pullで最新を持ってきます。

次に、flutterプロジェクトのbinディレクトリにパスを通します。

```bash
% cd ./flutter
% export PATH=`pwd`/bin:$PATH
```

ここでおもむろに`flutter`コマンドを叩いたら、

```bash
% flutter                                                                                                       
Updating flutter tool...
```

と出てきたので、`flutter`コマンドだけでFlutterのアップグレードが出来るんですかね……？（`flutter upgrade`というコマンドもありました）

`flutter --version`を実行して、確かにFlutterが使えるようになっていることを確認します。

```bash
% flutter --version
Flutter
Repository: https://github.com/flutter/flutter.git
Branch: alpha
Revision: 9487197502b5fcbe14a6b2de91ed51b95f5297d5 (26 hours ago)
```


# Flutterプロジェクトの作成

Flutterプロジェクトを作成してみます。

Flutterプロジェクトの作成には、`flutter init`コマンドを使用します。

`flutter init`コマンドの詳細は、以下のようになります。

```bash
% flutter init --help                                                                                            
Create a new Flutter project.

Usage: flutter init [arguments]
-h, --help        Print this usage information.
-o, --out         The output directory.
    --[no-]pub    Whether to run "pub get" after the project has been created.
                  (defaults to on)
```

`-o`オプションで、Flutterプロジェクトの出力先を指定します。

では作ってみます。

```bash
% cd <お好きなディレクトリ>
% flutter init -o flutter_sample
```

すると、Flutterプロジェクトの作成と、依存パッケージのダウンロードが始まります。

```bash
% flutter init -o flutter_sample
Creating flutter_sample...
flutter_sample/.gitignore
flutter_sample/flutter.yaml
flutter_sample/pubspec.yaml
flutter_sample/README.md
flutter_sample/lib/main.dart
flutter_sample/apk/AndroidManifest.xml

Running pub get in flutter_sample...
Resolving dependencies...
+ analyzer 0.27.0

+ args 0.13.2
+ async 1.4.0
+ barback 0.15.2+7
+ cassowary 0.1.7 from path ../flutter/packages/cassowary

+ charcode 1.1.0

+ collection 1.2.0
+ convert 1.0.1
+ crypto 0.9.1
+ csslib 0.12.2
+ flutter 0.0.21 from path ../flutter/packages/flutter
+ glob 1.0.5
+ html 0.12.2
+ http_multi_server 1.3.2 (2.0.0 available)
+ http_parser 1.1.0
+ intl 0.12.4+3 (0.12.5-dev available)
+ logging 0.11.2
+ matcher 0.12.0+1
+ material_design_icons 0.0.3
+ mime 0.9.3
+ mojo 0.4.8
+ mojo_apptest 0.2.12
+ mojo_sdk 0.2.7
+ mojo_services 0.4.10
+ mojom 0.2.12
+ newton 0.1.5 from path ../flutter/packages/newton
+ package_config 0.1.3
+ path 1.3.9
+ petitparser 1.5.0
+ plugin 0.1.0
+ pool 1.2.1
+ pub_semver 1.2.3
+ shelf 0.6.4+2
+ shelf_static 0.2.3+1
+ shelf_web_socket 0.0.1+4
+ sky_engine 0.0.71
+ sky_services 0.0.71
+ source_map_stack_trace 1.0.4
+ source_maps 0.10.1
+ source_span 1.2.1
+ stack_trace 1.5.0
+ string_scanner 0.1.4
+ test 0.12.6+1
+ typed_data 1.1.1
+ utf 0.9.0+2
+ vector_math 1.4.3
+ watcher 0.9.7

+ yaml 2.1.7
Downloading material_design_icons 0.0.3...
Downloading sky_engine 0.0.71...
Downloading sky_services 0.0.71...
Downloading mojo_sdk 0.2.7...
Downloading mojo_apptest 0.2.12...

Downloading mojo 0.4.8...
Downloading mojom 0.2.12...
Downloading mojo_services 0.4.10...
Downloading intl 0.12.4+3...
Changed 48 dependencies!
Precompiling dependencies...
Loading source assets...

Precompiled intl.
All done! To run your application:

  $ cd flutter_sample
  $ flutter start
```

自分の環境で10数秒かかりましたが、これでFlutterプロジェクトが作成されたはずです。

確かめてみましょう。

```bash
% cd flutter_sample
% ls
README.md    apk          flutter.yaml lib          packages     pubspec.lock pubspec.yaml
```

出来てます！ :clap::clap::clap::clap::clap:


# Androidでアプリを実行してみる

Android開発環境が整っている前提で説明を進めます。（`adb`コマンドにパスが通っている必要があります）

Flutterプロジェクトの作成時に以下のようなメッセージが出ています。

```bash
All done! To run your application:

  $ cd flutter_sample
  $ flutter start
```

プロジェクトのルートディレクトリで`flutter start`を実行すれば、アプリが実行できるようです。

```bash
% flutter start
Downloading darwin-x64 artifacts from the cloud, one moment please...
Downloading android-arm artifacts from the cloud, one moment please...
severe: Unable to run application - no connected devices.
```

おっと、「デバイスが接続されていません」と出てしまいました。Android端末をマシンに接続して試してみます。

```bash
% flutter start
Installing SkyShell.apk on device.
```

![Screenshot_2015-12-13-17-40-45.png](https://qiita-image-store.s3.amazonaws.com/0/636/c6514724-bba2-bfa1-8b5e-f406c72da2a2.png)

アプリが動きました！ :clap::clap::clap::clap::clap:


# iOS向けでのアプリ実行は？

まだ手軽に実行する手順が用意されていないようなので、今回は省きます。


# アプリを簡単に改造してみる

作成したFlutterプロジェクトに、lib/main.dartというファイルができています。

こちらのファイルを覗いてみます。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    new MaterialApp(
      title: "Flutter Demo",
      routes: {
        '/': (RouteArguments args) => new FlutterDemo()
      }
    )
  );
}

class FlutterDemo extends StatelessComponent {
  Widget build(BuildContext context) {
    return new Scaffold(
      toolBar: new ToolBar(
        center: new Text("Flutter Demo")
      ),
      body: new Material(
        child: new Center(
          child: new Text("Hello world!")
        )
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(
          icon: 'content/add'
        )
      )
    );
  }
}
```

こちらの

```dart
child: new Text("Hello world!")
```

となっているところを、

```dart
child: new Text("こんにちは、世界！")
```

に変更して、再び`flutter start`を実行してみます。

```bash
% flutter start
```

![Screenshot_2015-12-13-22-42-43.png](https://qiita-image-store.s3.amazonaws.com/0/636/604e3e7f-b03e-3741-85f1-c48f87fdacf6.png)

中央のテキストの内容を変更することが出来ました。

コードの細かい内容については、今回は扱いません。

（変更前と変更後でスクリーンショットの時刻に大きく差があるのは、iOS向けのビルドに挑戦して、結局今回やめたから、というのは内緒）

# 今後の期待

iOS向け、またはデスクトップ向けのビルドの方法が整備されていくと、本格的なアプリ開発が捗りそうです。

現時点(2015/12/13)では、flutterコマンドから手軽にiOS向けのビルドする方法は無いのですが、Flutterのコントリビューター向けの（内部仕様むき出しの）ビルド方法はあるようです。そちらの説明は @kyorohiro さんに期待します。

あと、今後Flutterの開発が進んでいくと、Androidアプリ開発のデファクトスタンダードがJava/AndroidSDKからDart/Flutterに変わっていくのではないかと期待しています。

さらに、Android OS自体にDartVMやFlutterが乗れば、その傾向は加速するでしょう。（AndroidチームとFlutterチームとDartチームのチーム間で、ぜひとも協力してほしい！）