2022/5/23/Flutter/How to write a Flutter pluginの訳パート1



How to write a Flutter plugin

1. Introduction

Welcome to the “How to write a Flutter plugin” codelab!

Just what is a plugin?

“How to write a Flutter plugin” codelabへようこそ。



A plugin is a piece of software that adds capabilities to your app.



For example, you might want your mobile app to interact with the camera on your device.



Plugins are an important part of the Flutter ecosystem. You should first check pub.dev to see if the plugin you need already exists.



The authors of the Flutter SDK, as well as members of the Flutter community, have written many plugins and published them to pub.dev to share them with the community.

Flutter SDKの作者やFlutterコミュニティのメンバーは、多くのプラグインを書き、コミュニティと共有するためにpub.devに公開しています。


In particular, you should check out the Flutter Favorite packages and plugins.

特にFlutter Favorite packages and pluginsをチェックしてください。


The Flutter Favorite Favorites tag identifies plugins that you should first consider when building your apps.

Flutter Favorite Favoritesタグはあなたがアプリを作る時にはじめに考えるべきpluginを示しています。


Note: This is an advanced topic and is not intended for Flutter beginners. Some Flutter developers may never write a plugin.


Flutter makes it easy for users to interact with cross-platform Dart libraries, but sometimes it’s ideal to interact with platform-specific code.



For example, you might want to communicate with a database that doesn’t have a Dart library written for it.



Flutter provides a mechanism for authoring plugins that allows you to communicate with platform-specific code and also allows you to publish your plugins on pub.dev so that others can use them.



In this codelab, you’ll learn how to author your own plugins for iOS and Android.



You’ll implement a simple music plugin that processes audio on the host platform, and then you’ll make an example app that uses your plugin to make a music keyboard.


Here are screenshots of the final app:



What you learn

  • How to write a Flutter plugin for iOS and Android.
  • How to create an API for your plugin.
  • How to write an app that uses your plugin.
  • How to publish your plugin so that others can use it.





2. Set up your Flutter environment

You need two pieces of software to complete this lab: the Flutter SDK and an editor. You can use your preferred editor, such as Android Studio or IntelliJ with the Flutter and Dart plugins installed, or Visual Studio Code with the Dart Code and Flutter extensions.

このラボを完了するには、Flutter SDKとエディターの2つのソフトウェアが必要です。FlutterとDartプラグインをインストールしたAndroid StudioやIntelliJ、Dart CodeとFlutter拡張をインストールしたVisual Studio Codeなど、お好みのエディターを使用することができます。


Some of the tooling for plugin development recently changed, so this codelab assumes v1.15.19 or later of the Flutter SDK. You can check your version with the following command:

最近、プラグイン開発用のツールの一部が変更されたため、このコードラボではFlutter SDKのv1.15.19以降を想定しています。以下のコマンドでバージョンを確認することができます。

$ flutter doctor

3. Generate the plugin template

Flutter ships with templates for plugins that make it easy to get started. When you generate the plugin template, you can specify which language you want to use. The default is Swift for iOS and Kotlin for Android. For this codelab, you use Objective-C and Java.



Run the following commands in your working directory to create the plugin template:


$ flutter create --template=plugin --org com.example --platforms=android,ios -a java -i objc plugin_codelab
$ cd plugin_codelab
$ cd example
$ flutter pub upgrade
$ dart migrate --apply-changes

These commands generate the following directory structure:



Here is a description of some important files:


  • pubspec.yaml—The YAML file that defines your plugin. It specifies the plugin’s name, dependencies, version, supported operating systems, and so on. This is used on your plugin’s pub.dev page.

プラグインを定義する YAML ファイルです。プラグインの名前、依存関係、バージョン、サポートされるオペレーティングシステムなどを指定します。このファイルはプラグインの pub.dev ページで使用されます。


  • CHANGELOG.md—Any time that you want to publish a new version of a plugin you must update this markdown file to indicate the changes in the new version.



  • README.md—This markdown file shows up on the front page of the plugin’s pub.dev listing. It should describe, in detail, what the plugin is and how to use it.



  • lib/plugin_codelab.dart—The Dart code that implements the frontend to your plugin. Plugin clients have access to the public classes and functions in this directory.

lib/plugin_codelab.dart – あなたのプラグインのフロントエンドを実装する Dart コードです。プラグインクライアントはこのディレクトリにあるパブリッククラスと関数にアクセスすることができます。


  • android/src/main/java/com/example/plugin_codelab/PluginCodelabPlugin.java—The native Java code that implements the Android feature described in plugin_codelab.dart.

android/src/main/java/com/example/plugin_codelab/PluginCodelabPlugin.java-plugin_codelab.dart で説明されている Android の機能を実装したネイティブの Java コード。


  • example/—This directory contains a client of your plugin. While developing your plugin, you edit this file to see your plugin in action.



  • example/lib/main.dart—The Dart code that exercises your plugin. You build the example UI here.

example/lib/main.dart – あなたのプラグインを実行するDartのコードです。サンプルのUIはここで構築します。

4. Build and run the example

Run the examples on your iOS or Android device with the following instructions:


$ cd plugin_codelab/example
$ flutter run

You should see something like this:



Check out the generated code for the plugin’s frontend:



class PluginCodelab {
  static const MethodChannel _channel =
      const MethodChannel('plugin_codelab');

  static Future<String> get platformVersion async {
    final String version =
      await _channel.invokeMethod('getPlatformVersion');
    return version;

cf1e10b838bf60ee.png Observations(観察)

  • PluginCodelab is the class that users of your plugin invoke.



  • This class creates a MethodChannel that allows the Dart code to communicate with the host platform.

このクラスは、Dart コードがホストプラットフォームと通信するための MethodChannel を作成します。

MethodChannel(Platform channel)についてはこちらをどうぞ。

  • The plugin’s API has only one method, the property getter platformVersion. When someone calls this getter in Dart, the MethodChannel invokes the getPlatformVersion() method and asynchronously waits for a Stringto be returned.



  • It’s up to the platform-specific code to interpret the meaning of the getPlatformVersion message, and you’ll see that later.



Note about MethodChannels

The constructor for MethodChannel has two more optional parameters, the codec and the binaryMessenger. The default values are usually fine, but the codec decides how the parameters to invoke are encoded, and that codec should match the codec in the platform-specific code so that it can decode the messages. The binaryMessenger is associated with a specific Flutter engine, so, when you have more than one Flutter engine, this helps to wire up the channels correctly between the plugin and the engine.

MethodChannel のコンストラクタには、さらに 2 つのオプションのパラメータ、codecと binaryMessenger があります。通常はデフォルト値で問題ありませんが、codecは呼び出すパラメータがどのようにエンコードされているかを決定し、そのcodecはメッセージをデコードできるようにプラットフォーム固有のコードのcodecと一致させる必要があります。binaryMessengerは特定のFlutterエンジンと関連付けられているので、複数のFlutterエンジンを持っている場合、プラグインとエンジンの間のチャンネルを正しく配線するのに役立ちます。


Future<void> initPlatformState() async {
  String platformVersion;
  // Platform messages may fail, so we use a try/catch PlatformException.
  // Platform メッセージが失敗した時のためにtry/catch文でPlatformExceptionを捕捉します。
  try {
    platformVersion = await PluginCodelab.platformVersion;
  } on PlatformException {
    platformVersion = 'Failed to get platform version.';

  // If the widget was removed from the tree while the asynchronous platform
  // message was in flight, we want to discard the reply rather than calling
  // setState to update our non-existent appearance.
  // 非同期のplatformメッセージ処理中にwidgetがウィジェットツリーから削除された場合、
  // 存在しないウィジェットをsetStateで更新せずに応答を無視します。
  if (!mounted) return;

  setState(() {
    _platformVersion = platformVersion;

cf1e10b838bf60ee.png Observations(観察)

  • This is a client of the plugin.



  • This code calls the getter defined in lib/plugin_codelab.dart.

このコードは、lib/plugin_codelab.dart で定義されているゲッターを呼び出します。


  • Notice that the call is wrapped in a try-block. If the platform-specific code for iOS returns a FlutterError, or an exception is thrown in Java, then it gets resurfaced on the Dart side.



Why is communication with a plugin asynchronous?


Flutter’s Dart code executes on a different thread than platform code (in Flutter engine nomenclature these are the UI thread and the platform thread, respectively). The serialized messages are sent from Dart’s thread, to the platform thread, and back for the result.



+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
            binaryMessenger:[registrar messenger]];
  PluginCodelabPlugin* instance = [[PluginCodelabPlugin alloc] init];
  [registrar addMethodCallDelegate:instance channel:channel];

cf1e10b838bf60ee.png Observations

  • This initialization code is called when a new engine is set up.



  • This code generates a channel for communicating with the plugin.



  • Notice that the channel name specified here must match the name defined in lib/plugin_codelab.dart.



  • Setting itself up as the methodCallDelegate means that the created instance receives messages that are associated with the provided binary messenger.



- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"getPlatformVersion" isEqualToString:call.method]) {
    result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
  } else {

cf1e10b838bf60ee.png Observations(観察)

  • This Objective-C code implements the getPlatformVersion() method for iOS.





public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
  channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "plugin_codelab");

cf1e10b838bf60ee.png Observations

  • This Java code implements getPlatformVersion() for Android.



public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
  if (call.method.equals("getPlatformVersion")) {
    result.success("Android " + android.os.Build.VERSION.RELEASE);
  } else {

cf1e10b838bf60ee.png Observations

  • This Java code handles messages sent from Dart. Notice that this code is similar in form to the iOS plugin, but has some subtle differences.


パート2へ >>




メールアドレスが公開されることはありません。 が付いている欄は必須項目です