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

 

Contents

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へようこそ。

pluginとは何でしょう?

 

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

pluginはあなたのアプリにいろいろな機能を追加するソフトウェアのことです。

 

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.

pluginはFlutterエコシステムの中で重要な役割を担います。まずあなたの求めているpluginがpub.devにすでに存在しているかをまずチェックしてみてください。

 

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ビギナー向けではありません。pluginを書かないFlutter開発者もいます。


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

Flutterは、ユーザーがクロスプラットフォームのDartライブラリと簡単にやりとりできるようにしますが、時にはプラットフォーム固有のコードとやりとりするのが理想的な場合もあります。

 

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

例えば、Dartのライブラリが書かれていないデータベースと通信したい場合があります。

 

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.

Flutterはプラグインをオーサリングするための仕組みを提供しており、プラットフォーム固有のコードと通信することができます。また、プラグインをpub.devで公開し、他の人が使用できるようにすることもできます。

 

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

このコードラボでは、iOSと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:

最終的なアプリのスクリーンショットです。

4c37cf5f5086a72f.png

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.

iOS/Android用のFlutterのpluginを書く方法。

plugin用のAPIを作る方法。

pluginを使ったアプリを書く方法。

あなたのpluginを公開する方法。


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.

Flutterにはプラグイン用のテンプレートが同梱されており、簡単に使い始めることができます。プラグインテンプレートを生成する際に、使用する言語を指定することができます。デフォルトでは、iOSはSwift、AndroidはKotlinです。このコードラボでは、Objective-Cと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.

CHANGELOG.md-プラグインの新しいバージョンを公開したい場合はいつでも、このマークダウンファイルを更新して、新しいバージョンでの変更点を示す必要があります。

 

  • 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.

README.md-このマークダウン・ファイルはプラグインのpub.devリストのトップページに表示されます。このファイルはプラグインが何であり、どのように使うかを詳細に記述します。

 

  • 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/-このディレクトリには、あなたのプラグインのクライアントが含まれています。プラグインの開発中に、このファイルを編集して、プラグインの動作を確認します。

 

  • 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:

iOSまたはAndroidデバイスで、以下の手順でサンプルを実行してください。

$ cd plugin_codelab/example
$ flutter run

You should see something like this:

下記のようになると思います。

ab5a376b155a38cf.png

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

生成されたプラグインのフロントエンドのコードを確認します。

lib/plugin_codelab.dart

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.

PluginCodelabクラスは、ユーザーがあなたのプラグインを実行するためのクラスです。

 

  • 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.

プラグインのAPIには、プロパティゲッターであるplatformVersionというメソッドが1つだけあります。Dartでこのゲッターを呼び出すと、MethodChannelはgetPlatformVersion()メソッドを呼び出し、非同期的に、Stringが返されるのを待ちます。

 

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

getPlatformVersionメッセージの意味を解釈するのは、プラットフォーム固有のコード次第で、それは後で見ることになります。

 

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エンジンを持っている場合、プラグインとエンジンの間のチャンネルを正しく配線するのに役立ちます。


example/lib/main.dart

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.

これは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.

この呼び出しはtry-blockでラップされていることに注目してください。iOSのプラットフォーム固有のコードがFlutterErrorを返すか、Javaで例外が発生した場合、Dart側で付け替えられます。(例外が捕捉されて例外処理が行われる、という意味。)

 

Why is communication with a plugin asynchronous?

なぜpluginとネイティブ側の交信は非同期的に行うのですか?

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.

FlutterのDartコードはプラットフォームコードとは別のスレッドで実行されます(Flutterエンジンの命名法では、それぞれUIスレッドとプラットフォームスレッドとなります)。シリアライズされたメッセージはDartのスレッドからプラットフォームのスレッドに送られ、そしてその結果が(Dartのスレッドに)返されます。


ios/Classes/PluginCodelabPlugin.m

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"plugin_codelab"
            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.

このコードはpluginと交信するためのチャンネルを生成します。

 

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

ここで指定するチャンネル名('plugin_codelab')は、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.

methodCallDelegateとして自身を設定することは、生成されたインスタンスが、提供されたバイナリメッセンジャーに関連するメッセージを受け取ることを意味します。


ios/Classes/PluginCodelabPlugin.m

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

cf1e10b838bf60ee.png Observations(観察)

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

このObjective-Cのコードは、getPlatformVersion()メソッドのiOS側の実装ということになります。

 

結果コールバックはNSStringパラメータで呼び出され、このパラメータはメソッドチャネルのコーデックによって自動的に変換されます。


android/src/main/java/com/example/plugin_codelab/PluginCodelabPlugin.java

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

cf1e10b838bf60ee.png Observations

  • This Java code implements getPlatformVersion() for Android.

このJavaのコードは、getPlatformVersion()メソッドのAndroid側での実装ということになります。


android/src/main/java/com/example/plugin_codelab/PluginCodelabPlugin.java

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

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.

このJavaコードは、Dartから送信されたメッセージを処理します。このコードはiOSのプラグインと形は似ていますが、微妙な違いがあることに注意してください。

パート2へ >>

参考

https://codelabs.developers.google.com/codelabs/write-flutter-plugin#0

コメントを残す

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