LoginSignup
16
5

More than 5 years have passed since last update.

Flutter - Developing Packages & Plugins (日本語訳)

Last updated at Posted at 2018-09-10

Developing Packages & Plugins の日本語訳

Package introduction

最小のパッケージは以下を含む:

  • pubspec.yaml
  • lib ディレクトリ。ここにコードを置く。最低限 .dart が必要。

パッケージの種類

Dart パッケージ: Dart で書かれたパッケージ。いくつかのものは Flutter 固有の機能を持ち、したがって Flutter フレームワークに依存し Flutter のためにのみ使用できる。例 https://pub.dartlang.org/packages/fluro

プラグインパッケージ: Dart で書かれた特別なパッケージで、Android (using Java or Kotlin) や iOS (using ObjC or Swift) などプラットフォーム固有の実装を含む。例 https://pub.dartlang.org/packages/battery

Developing Dart packages

Step 1: Create the package

Dart パッケージを作るには --template=package フラグとともに flutter create コマンドを実行する:

$ flutter create --template=package hello

以下を含む hello/ ディレクトリが作られる。

  • live/hello.dart: パッケージの Dart コード
  • test/hello_test.dart: パッケージのユニットテスト

Step 2: Implement the package

純粋な Dart パッケージは lib/<package name>.dart に機能を実装するか、lib ディレクトリ以下のいくつかのファイルに実装する。パッケージをテストするために test ディレクトリにユニットテストを追加する。パッケージの構造の詳細については次を参照 Dart library package

Developing plugin packages

もしプラットフォーム固有の機能を呼び出す必要があるならプラグインパッケージを作る必要がある。プラグインパッケージは Dart パッケージ の特別なバージョンで、先の説明にもあったように Android (using Java or Kotlin) や iOS (using ObjC or Swift) などプラットフォーム固有の実装を含む。その API は platform channels を使ってプラットフォーム固有の実装と連携する。 https://flutter.io/platform-channels/

Step 1: Create the package

プラグインパッケージを作るには --template=plugin フラグとともに flutter create コマンドを実行する。--org オプションを使ってあなたの組織を逆ドメイン名表記で指定する。この値は様々なパッケージや自動生成された Android と iOS のコードに含まれる bundle identifiers に使われる。

$ flutter create --org com.example --template=plugin hello

以下のを含む hello/ ディレクトリが作られる:

  • live/hello.dart: プラグインの Dart API
  • android/src/main/java/com/example/​hello/HelloPlugin.java: Android 用のプラグインAPIの実装
  • ios/Classes/HelloPlugin.m: iOS 用のプラグインAPIの実装
  • example/: プラグインに依存するサンプルアプリ

デフォルトではプラグインは Objective-C と Java をそれぞれ iOS、Android のために使用する。必要に応じて -i オプションと -a オプションで Swift や Kotlin を指定することができる:

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

Step 2: Implement the package

プラグインパッケージは異なる言語で書かれたプラットフォーム固有のコードをもつが、使いやすくするためにいくつかの固有のステップが必要になる。

Step 2a: プラグインパッケージ API (.dart) を定義

プラグインパッケージの API は Dart コードで定義される。hello/ ディレクトリを開いて lib/helllo.dart を作る。

Step 2b: Android プラットフォームコード (.java/.kt) を追加

Android プラットフォームコードを Android Studio で編集する前にコードを一度ビルドする。(IDE から実行するか、次のようにして cd hello/example; flutter build apk

次に

  • Android Studio を起動
  • Welcome to Android Studio ダイアログで import project を選択、もしくはメニューから File > New > Import Project… を選択し、hello/example/android/build.gradle を選択する
  • Gradle Sync ダイアログで OK を選択
  • Android Gradle Plugin Update ダイアログで Don’t remind me again for this project を選択

Android プラットフォームコードは hello/java/com.example.hello/​HelloPlugin に置かれる。▶︎ボタンを押してアプリを実行することができる。

Step 2c: iOS プラットフォームコード (.h+.m/.swift) を追加

Xcode で iOS プラットフォームコードを編集する前にコードを一度ビルドする(IDE から実行するか、次のようにして cd hello/example; flutter build ios --no-codesign

次に

  • Xcode を起動
  • File > Open を選択し、hello/example/ios/Runner.xcworkspace を選択する

iOS プラットフォームコードはプロジェクトナビゲーター上で Pods/DevelopmentPods/hello/Classes/ に置かれる。▶︎ボタンを押してアプリを実行することができる。

Step 2d: API とプラットフォームコードの接続

最終的に、Dart コードで書かれた API とプラットフォーム固有の実装を接続する必要がある。そのために platform channels を使う https://flutter.io/platform-channels/

ドキュメントの追加

全てのパッケージは以下のドキュメントを持つことが望ましい:

  • README.md - パッケージの説明
  • CHANGELOG.md - それぞれのバージョン毎の変更
  • LICENSE - パッケージのライセンス
  • 全てのパブリックAPI についての API ドキュメント(詳細は以下を参照)

API ドキュメント

プラグインパッケージを公開すると API ドキュメントが自動で生成され、 dartdocs.org に公開される。例 https://pub.dartlang.org/documentation/device_info/0.0.4/index.html

API ドキュメントをローカルマシンで生成したい場合は以下のようにする:
1. パッケージディレクトリに移動
cd ~/dev/mypackage
2. ドキュメンテーションツールに Flutter SDK の場所を伝える
export Flutter_ROOT=~/dev/flutter (macOS or Linux), 
set Flutter_ROOT=~/dev/flutter (Windows)
3. dartdoc を実行(dartdoc は Flutter SDK に含まれる)
$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dartdoc (macOS or Linux)
%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dartdoc (Windows)

API ドキュメントを書く為の Tips についてはこちらを参照 https://www.dartlang.org/guides/language/effective-dart/documentation

パッケージの公開

パッケージを実装したら、他の開発者が見つけやすいように Pub に公開することができる。
公開する前に pubspec.yaml, README.md, CHANGELOG.md の内容が正しいかレビューする。

次に、dry-run コマンドを実行して全ての analysis をパスすることを確認する:

$ flutter packages pub publish --dry-run

最後に、実際のパブリッシュコマンドを実行する:

$ flutter packages pub publish

パッケージの公開について詳細はこちらを参照 https://www.dartlang.org/tools/pub/publishing

パッケージの依存関係の取り扱い

もし hello というパッケージを作っていて、それが他のパッケージの Dart API に依存している場合、 pubspec.yaml ファイルの dependencies セクションにそのパッケージを追加する必要がある。以下のコードは url_launcher プラグインの Dart API を hello で利用可能にする:

hello/pubspec.yaml

dependencies:
  url_launcher: ^0.4.2

これで import 'package:url_launcher/url_launcher.dart' して launch(someUrl) を実行できるようになる。これは Flutter アプリや Dart プロジェクトでパッケージを含めるのとなんら変わらない。しかし、もし hello が url_launcher が公開しているプラットフォーム固有の処理にアクセスする場合、プラットフォーム固有のビルドファイルに適切な依存関係を追加する必要がある。

Android

hello/android/build.gradle:

android {
    // lines skipped
    dependencies {
        provided rootProject.findProject(":url_launcher")
    }
}

これで import io.flutter.plugins.urllauncher.UrlLauncherPlugin して UrlLauncherPluginhello/android/src 以下のコードからアクセスできる。

iOS

hello/ios/hello.podspec:

Pod::Spec.new do |s|
  # lines skipped
  s.dependency 'url_launcher'

これで #import "UrlLauncherPlugin.h" して UrlLauncherPlugin クラスに hello/ios/Classes 以下のクラスからアクセスできるようになる。

コンフリクトの解消

次のようなケースを想像してください。あなたは some_packageother_package をあなたの hello パッケージで使いたい。そして両方とも url_launcher に依存しているが別のバージョンである。このときコンフリクトが起こりうる。最前の解決策として、依存関係を指定するときに特定のバージョンを指定するのではなく version ranges を指定する。 https://www.dartlang.org/tools/pub/dependencies#version-constraints

dependencies:
  url_launcher: ^0.4.2    # Good, any 0.4.x with x >= 2 will do.
  image_picker: '0.1.1'   # Not so good, only 0.1.1 will do.

もし some_package が上のような依存バージョンを指定していて、 other_package が url_launcher の '0.4.5' や '^0.4.0' を指定していた場合、pub はその依存関係を解決することができる。Grade module や Cocoa pods においても似たような方法をとることができる。

たとえ some_package と other_package が url_launcher について非互換なバージョンを指定していたとしても、互換性のある方法で url_launcher を使うことができる。この場合、コンフリクトは hello の pubspec.yaml に dependency override 追加して特定のバージョンを強制することで対処される。

hello/pubspec.yaml で url_launcher '0.4.3' を強制する:

dependencies:
  some_package:
  other_package:
dependency_overrides:
  url_launcher: '0.4.3'

もしコンフリクトがパッケージ自体によるものではなく、Android の特定のライブラリによるものであった場合、Gradle ビルドロジックに代わりに dependency override を追加する必要がある。

hello/android/build.gradle で guava '23.0' を強制する:

configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:23.0-android'
    }
}

Cocoapods は現在 dependency override 機能を提供していない。

16
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
5