既存アプリを一部Flutter化する(Add-to-app)

Flutterには既存のNativeアプリの一部分をFlutter化するソリューションである[Add-to-app](https://flutter.dev/docs/development/add-to-app)が存在するので試してみる。

Androidでは特定のActivityをFlutter化出来たり、特定のFragmentをFlutter化出来たりと結構柔軟に対応できそうである。
iOSに関しては特定のViewControllerをFlutter化可能である。

Flutter Module（Flutter化された画面というか普通にFlutterの部分）を作成して、Android、iOSそれぞれから呼び出すまでの手順を示す。

# 制限
Flutter v1.12　Add-to-appには下記制限が存在する。

- 複数のFlutterインスタンスを動作させたり、Viewの一部で動作させると挙動がおかしくなる可能性がある。
- [バックグラウンド動作モード](https://flutter.dev/docs/development/packages-and-plugins/background-processes)は試作中
- 複数のFlutterライブラリをアプリに同封するのはサポートされていない
- add-to-appで使用する[FlutterPlugin](https://flutter.dev/docs/development/packages-and-plugins/developing-packages)は最新の「new Android plugin API」に対応してないといけない
    - Flutter Activityが常に存在しているなどを想定した動作を実装していると挙動がおかしくなる可能性がある。
- AndroidXアプリしかサポートしていない

# Androidプロジェクトへの組み込み、実行
Androidプロジェクト上でFlutterModuleを作成、実行。その後同ModuleをiOSに組み込むという手順で実施してみる。

## Flutter Module作成

[公式](https://flutter.dev/docs/development/add-to-app/android/project-setup)に記載されている「Using Android Studio」の章通りに実行すれば可能。
FlutterModuleのプロジェクトがAndroidアプリとは別のディレクトリに作成されて、Android Studio上で上手に内包される感じになる。
後にこのFlutterModuleのプロジェクトをiOSのプロジェクトにも取り込む。

## Flutter Moduleの実行方法

[公式](https://flutter.dev/docs/development/add-to-app/android/add-flutter-screen)通りに実行すれば問題ない。

実行方法を大きく分けるとFlutterActivityを生成して単一画面上で実行する方法と、FlutterFragmentを生成して臨機応変な場面で実行する方法に別れる。
基本的にはシンプルなFlutterActivityでの実行を推奨している。
※iOSはViewControllerでの実行しかサポートしていないので、単一画面上でしか実行出来ないものと思われる（すみませんここはiOSそこまで詳しくないです）。となると同一FlutterModuleをAndroidでもiOSでも流用すると考えるとFlutterActivityでの実行を選択することになると思われる。

 - FlutterActivity
    - 普通にActivityを起動する感じ
    - 初期Rootを指定できる
    - FlutterEngineが起動する時間があるので、予めEngineを起動してスタートする事も可能
 - FlutterFragment
    - ActivityのFragment版
    - 基本はシンプルなActivityを使用することを推奨している
    - いろんなActivityのコールバックをFlutterFragmentに通知する必要がある

### Pluginのマネジメント

[firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics)プラグインみたいにAndroidアプリのGradleの編集を要求するようなプラグインを使用する場合には[別途対応](https://flutter.dev/docs/development/add-to-app/android/plugin-setup)が必要である。

# iOSプロジェクトへの組み込み、実行

上記で作成したFlutter ModuleをiOSのプロジェクトに組み込んで起動するまでの手順を示す。

## iOSプロジェクト作成

Flutter Moduleは作成済みなので[公式](https://flutter.dev/docs/development/add-to-app/ios/project-setup)の「Embed the Flutter module in your existing application」の章からCocoaPodsを利用した組み込みを実施する。

1. Xcodeで新規のStoryboardプロジェクトを作成
2. CocoaPodsを適用

```shell
$ cd プロジェクトパス
$ pod init
$ pod install
Please close any current Xcode sessions and use `Flutter_test.xcworkspace` for this project from now on.
Pod installation complete! There are 0 dependencies from the Podfile and 0 total pods installed.
```

3．Flutterへの依存をPodfileに記載

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200860/c2aa7bf1-e949-35f3-ebd7-56a6ccfefca3.png)

flutter_application_pathに設定するのがAndroid Studioから作成したFlutter Moduleへのパスである。

4．依存を解消

```shell
$ pod install
```

## Flutter Moduleの実行方法

[公式](https://flutter.dev/docs/development/add-to-app/ios/add-flutter-screen?tab=engine-swift-tab)に書いてあるとおりに実行すればFlutterが走るViewControllerが起動する。
Androidと同様FlutterEngineを予め起動することが可能である。

# 参考
https://flutter.dev/docs/development/add-to-app

https://qiita.com/imamurh/items/43966e33e100956e0998