azihsoyn's blog

技術のこととか釣りの事とか(書けたらいいなぁ)

flutterでネイティブplugin作ってみた振り返り

最近寒くないですか???

この記事は Flutter Advent Calendar 2018 - Qiita 12日目の記事です。 昨日は aoinakanishi さんの Google公式Flutter用WebViewプラグインを一通り使ってみた でした。

さてもともとはネイティブpluginの作り方という内容で書こうかなと思っていたのですが、 公式サイトDeveloping packages & plugins - Flutter を見れば済む話なのと、Qiitaに翻訳記事 Flutter - Developing Packages & Plugins (日本語訳) もあったので特にやることがなくなってしまいました。

なので実際に作って公開してみてわかったこととかを思い出しながら振り返ってみたいと思います。年末ですし。

作ったもの

github.com

Google I/O 2018で発表されたfirebaseの機能の一つである ML Kit をflutterで使えるようにしたやつです。

Firebase Japan User Group / Google IO 2018 報告会 で発表してきました! - Gunosy Tech Blog

Google I/O に参加して意識が高まってたときにflutterで勉強会に登壇することを決め、なにかネタが欲しいと思って作ってみたのがきっかけでした。

それがまさかスター100を超えるとは思っても見ませんでした。それだけflutterとMLKitの需要が高かったんだなと思います。

当時はまだ公式のpluginはありませんでしたが、そこは開発速度の早いflutter、今はちゃんと提供されています。

github.com

flutter公式で提供するpluginは全て https://github.com/flutter/plugins で管理する運用みたいです。

公式のpluginが出たのでそこまでがっつり機能追加していくつもりはないですが何気に カスタムモデル にも対応していたりするので気が向いたら使ってみてください。動かないとかは修正するつもりです。

さて宣伝はここまでにして、以下plugin開発で得た知見とか参考になりそうなことを。

参考になりそうなこと

公式リポジトリに参考になるコードがたくさんある

上でも述べましたが https://github.com/flutter/plugins にはたくさんのpluginが用意されています。 pluginを作るときはまずここを参考にすると良いと思います。

ネイティブpluginには以下の2つの機能があると思っていて、

  1. ネイティブ側でなにか処理をしてflutter側に値を返す
  2. ネイティブ側のViewをflutter側でも表示する

1のような機能を作りたいときは

あたりを参考にすると良いと思います。

2の機能だと

あたりでしょうか。

また、1の機能を実装する上で必ず見ることになるのが

flutter.io

dartとネイティブの型の対応表です。

公開しなくてもpluginを読み込める

plugin開発のページでは公開する方法として flutter pub コマンドを紹介しています。

flutter.io

pubコマンドでpublishされたpluginは https://pub.dartlang.org/flutter/packages に公開されます。

ただ、このコマンドはGoogleのCLAに同意する必要があったり、パブリックになってしまうため開発中に使うには少しハードルが高い気がします。

そういう場合は gitのリポジトリから直接pluginを読み込むことができます。

flutter.io


これ最初からあったんでしょうか?自分が最初plugin作り始めたときはなかったような🤔もっと早く知りたかったやつです。

公式pluginsの言語はJava/Obj-C

flutter公式のpluginに機能を追加したい場合は普通にPRを出せばレビューしてくれます。

今の所言語はJava/Obj-Cで実装していくポリシーみたいです。

github.com

そういう意味では参考になるコードがあると言ってもJava/Obj-Cに慣れてないと辛いかもしれません(辛い)。

ただplugin自体は当然Kotlin/Swiftでも書けますし flutterのコマンドでも言語を指定できます。

$ flutter create --template=plugin -i swift -a kotlin hello

flutter.io

慣れてる言語で書くのが良いと思います。

依存パッケージ問題はむずい

flutterに限らずパッケージの依存関係を管理するのは難しいです。 ネイティブ側で使う依存ライブラリは

  • iOSでは .podspec
  • Androidでは build.gradle

指定することでflutterからも呼び出すことができます。

これは1つのplugin内では特に問題は起きないのですが、他のpluginと同じライブラリを使っていると一気にハードルが上がります。 というか多分どっちかのライブラリが対応しないと同時に使えないとか普通に起きる気がします。

firebaseのSDKは開発スピードが早く機能追加が頻繁に行われるのでライブラリのバージョンも結構よく上がります。(semverとは...)

この問題の最適解は自分の中では出てませんが CocoaPods なら optimistic operator (~>)を使ってパッチバージョンのアップデートに追従しておくのがいいのかなと思ってます。

# 5.11.X までサポート
s.dependency 'Firebase/MLVision', '~> 5.11.0'

この場合依存ライブラリのアップデートがあったら対応が必要になりますが、勝手に依存ライブラリが上がって動かなくなるというのは防げる気がします(ライブラリのバージョニングのポリシーによりますが)。

公開後の分析を見る

pluginのリポジトリにはanalysis tabがあります。https://pub.dartlang.org/packages/mlkit#-analysis-tab-

ここではlint的なチェックや依存ライブラリ、対応してるflutterのバージョンなどによってスコアづけしてくれるみたいです。ここで提案されている修正は直したほうがいいと思います。

もしかしたら flutter analyze コマンドとかで公開前にわかるかもしれません。 flutter pub --dry-run でも出てきたかもしれません。

pluginの開発はAndroidStudioが多分良さそう

flutter pluginの開発はIDEがサポートしてれば何を使って書いても問題ないですが、AndroidStudioが便利です。

flutter pluginは、flutterとしてのプロジェクトとAndroidとしてのプロジェクトとiOSとしてのプロジェクトが共存しているような状態なのでIDEのコード補完を効かせるのに難儀します。

AndroidStudioではflutterプロジェクトの状態ではflutter補完が普通に効くのですが、その状態でAndroidのコードを編集しようとするとandroid用のimport pathが読めなくてIDEが真っ赤になると思います。

そんな時AndroidStudioの右上に出てくる Open On AndroidStudioをクリックするとAndroidプロジェクトとして開いてくれます。当然gradle syncが終われば補完が効きます。 同様にiOSのコードを開くとOpen on XCodeが出てくるので(macの場合) そのままXCodeで開けば補完に頼ってコードを書くことができます。

他のエディタを試していないのでなんとも言えないですがネイティブのコードを書く場合はAndroidStudio/XCodeを使ったほうがハマりどころが少ない気がします。

(例えばAppCodeにandroidとflutterのplugin入れたら1エディタで開発できるんでしょうか?🤔気になる...)

まとめ

flutterも1.0になったことだし、どんどんplugin作って行きましょう!(雑)

(そういえばhummingbirdでwebもflutterで書けるようになったらpluginのweb対応もあるのかな)


明日は superman9387 さんのエントリです。