Flutterプラグイン開発ことはじめ

これは[Supershipグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/supership)の3日目の記事です。

## 自己紹介
![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608850/18517075-7d09-448b-6704-5a9a23b69b94.png)
[Ad Generation](https://supership.jp/business/adgeneration/)というサービスで、 
iOS/Androidアプリ向けのSDKを開発している、 @napo と申します。

モバイルアプリは、Androidは4.1から、iOSは10からキャリアをスタートしました。
なので、比較的遅くからはじめた方だと思います。業務を通して気づきが多い日々を過ごしています。

今の願いとしては、iOS13以降をサポートすればシェア的に問題ない世界線に早くなって、
SwiftUI/Combineが気兼ねなく使える世の中になってほしいと感じています。

## なんの記事？
個人的にFlutter製のアプリが好きなので、Flutterコミュニティに何らか還元したいと思っています。
なので今回はFlutterのプラグインを開発する手順を簡単に説明したいと思います！

## やりたいこと
- Flutterアプリに導入できる自作のプラグインを用意できるようにする

## 要点
- Flutterライブラリに依存してDartだけで構築できる場合は `package` を作る
- Flutterから、iOS/AndroidのネイティブAPIにアクセスする必要がある場合は `plugin` を作る
- ドキュメントを充実させる
- 外部に公開は簡単だが、削除はできないので気をつける

## 環境
- Android Studio 4.1
- Xcode 12.2
- Flutter 1.22.4

## 手順
### ①環境構築
- Flutterの[環境構築](https://flutter.dev/docs/get-started/install)を済ませておく
- Flutterコマンドがterminalから利用できることを確認しておく

### ②pluginのテンプレートを作成する
- `flutter create` コマンドを利用して、任意のディレクトリでpluginのテンプレートを作成する
- 今回は下記のように `jp.co.hoge.fuga` というパッケージ名で、 `plugin` をAndroid,iOS向けに作成することにしました！

```shell:terminal.app
$ flutter create --org jp.co.hoge.fuga --template=plugin --platforms=android,ios FlPluginSample
```

flutter createコマンドのオプションは下記になります。

|オプション|指定できる値|補足|
|---|---|---|
|--org|任意の文字列||
|--template|`package` or `plugin`||
|--platforms|android / ios / web / linux / macos|,区切りで複数指定可能|
|--a|kotlin or java|defaultはkotlin|
|--i|swift or objc|defaultはswift|

### ③コードを実装する
- 主に変更するファイルたちは下記になります。
 - `/lib/[プラグイン名].dart` ファイル : パブリックAPIとなるメソッドを定義する
 - `/android/配下` : Androidプラットフォーム向けのコード
 - `/ios/配下` : iOSプラットフォーム向けのコード

- テンプレート作成時に追加されている、 `exsample` ディレクトリに移動し、AndroidとiOSをそれぞれ事前にビルドしておきます。

```shell:terminal.app
$ flutter build apk
```

```shell:terminal.app
$ flutter build ios --no-codesign
```

#### Android向けのコード
- Android Studioを起動し、 `[プラグイン名]/example/android/build.gradle` を選択してプロジェクトを開きます。
- プラグイン名のモジュールが存在していると思いますので、そちらを開いて、 `[プラグイン名]/java/[パッケージ名]/[プラグイン名]Plugin` というファイルに実装を追加していけばOKです。

#### iOS向けのコード
- Xcodeを起動し、 `[プラグイン名]/example/ios/Runner.xcworkspace` を選択してプロジェクトを開きます。
- プロジェクトナビゲータから `Pods/Development Pods/hello/../../example/ios/.symlinks/plugins/hello/ios/Classes`　配下のファイルに実装を追加していけばOKです。

つまり、Android Studio, Xcode上から、exsampleで自動追加されたテストアプリを実行しながら、直接プラグインのコードを修正できるということですね！
本当に作りやすく考えられていて、感動します。

#### パブリックAPIと各プラットフォームのコードを接続する
パブリックAPIを定義している、.dartと、Android, iOS向けにそれぞれ記述したコードを、
[platform-channels](https://flutter.dev/docs/development/platform-integration/platform-channels) を用いて実装をおこなう

### ④ドキュメントを記載する
- プラグインの挙動とは直接関係はないのですが、外部への公開を考えている場合、下記の4点が必要となります！
 - `README.md` そのプラグインの解説を記載したファイル
 - `CHANGELOG.md` 各バージョンでの変更を文書化したファイル
 - `LICENSE` そのプラグインの[ライセンスを記述](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#adding-licenses-to-the-license-file)する
 - パブリックにしているAPIに対して、[コメントを記述](https://dart.dev/guides/language/effective-dart/documentation)する(コメントを基に自動でdartdocが生成されAPIドキュメントとなる)

### ⑤プラグインを公開する
Flutterでは、 公式で[pub.dev](https://pub.dev/) というDartパッケージを一覧できるサイトがあります。
他の開発者にも使ってもらえるよう、公開したい場合は下記をおこなってください。

- 公開するプラグインが問題ないかを事前に --dry-run をおこなってチェックする

```shell:terminal.app
$ flutter pub publish --dry-run
```

- 問題なければ、下記コマンドで、プラグインを公開できます！ ※一度公開してしまうと、削除はできないので慎重に！

```shell:terminal.app
$ flutter pub publish
```


- 公開したプラグインは④で準備したドキュメントを基にしてスコアリングされます。

(下記は公式のパッケージ `provider` のスコアです)

![スクリーンショット 2020-12-02 13.10.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608850/c120b19a-0f3f-2316-fe5a-43ad4fec0ed3.png)

プラグインに対するスコアが視覚的にわかりやすいので、
ドキュメントを充実させたくなるモチベーションがあがるので楽しいですね！

### ⑥お疲れさまでした！
Flutterはドキュメントやサンプルが非常に充実していて、
何かハマっても、ちゃんと解決にたどり着けることが多いと感じています。

個人的にはFlutterというコミュニティが、もっともっと盛んになるよう心から願っています。

明日は、 @dictav さんの 「Sapperを使ったWebアプリケーション開発」　です！お楽しみに！

## 参考
- [Flutter](https://github.com/flutter/flutter)
- [pub.dev](https://pub.dev/)
- [Developing packages & plugins](https://flutter.dev/docs/development/packages-and-plugins/developing-packages)

## 最後に
Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は以下リンクよりご確認ください。
[Supership株式会社 採用サイト](https://supership.jp/recruit/)
是非ともよろしくお願いします。