Flutterで、Text To Speechをするために Pluginを作成したお話。
What is Flutter
- マテリアルデザインアプリを簡単に作成できるSDK
- AndroidとiOSの両方でビルド
- Googleによって開発されたオープンソースのツール
- 開発ツール(CLI)、使いやすい言語(Dart)、豊富なウィジェット(UI)、優れたIDEサポート(IntelliJ)を提供
Flutter Widget Framework
- UIはWidgetで構築。Reactからインスピレーションを得たリアクションスタイルのフレームワーク
- Dart VM 上で実行
- cf.A Tour of the Flutter Widget Framework - Flutter
Using Packages & Developing Plugins
- すでに多くのパッケージが公開されている。httpやデバイス向けAPI(バッテリー)など
- cf.Dart Packages
- 自らパッケージを開発することもできる
- cf.Developing Packages & Plugins
Custom platform-specific code with platform channels
- プラットフォームのコードを実行したい場合は、プラットフォームチャネルを使用する。
-
図のように、プラットフォームチャネルを使用してクライアントとプラットフォーム間でメッセージのやり取りを行う。
-
cf.Writing custom platform-specific code with platform channels - Flutter
Plugin at Flutter
- 任意の名前を指定して、MethodChannelを作成し、invokeMethodを定義する。
- invokeMethodには、プラットフォーム側に渡すメッセージと引数を定義。
class TtsPlugin {
// ttsのチャンネルを定義
static const MethodChannel _channel = const MethodChannel('net.granoeste.flutter.plugin/tts_plugin');
// speechメソッドが呼ばれたら、invokeMethodでプラットフォームへメッセージ通知
static Future speech(String text) => _channel.invokeMethod("speech", text);
static Future stop() => _channel.invokeMethod("stop");
static Future language(String language) => _channel.invokeMethod("language", language);
}
Implement Platform Code (Android)
プラグインの登録
public class TtsPlugin implements MethodCallHandler {
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel methodChannel = new MethodChannel(registrar.messenger(), "net.granoeste.flutter.plugin/tts_plugin");
TtsPlugin ttsPlugin = new TtsPlugin(registrar.activity(), methodChannel);
methodChannel.setMethodCallHandler(ttsPlugin);
}
private TtsPlugin(Activity activity, MethodChannel channel) {
this.activity = activity;
}
メッセージ受け取り時の実装
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("speech")) {
String speechText = call.arguments.toString();
// TODO: speech
result.success(true);
} else if (call.method.equals("stop")) {
// TODO: stopSpeech
result.success(true);
} else if (call.method.equals("language")) {
// TODO: set language
} else {
result.notImplemented();
}
}
App use plugin
基本的には、Pluginのメソッドを呼び出し、メッセージをプラットフォームへ伝えるだけ。
Future _textToSpeech() async {
final res = await TtsPlugin.speech("Hello world");
}
Future _language() async {
final res = await TtsPlugin.language("en");
}
プラグインの登録自体は、自動生成されたJavaのクラスのGeneratedPluginRegistrantで行ってくれます。
/**
* Generated file. Do not edit.
*/
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
TtsPlugin.registerWith(registry.registrarFor("net.granoeste.ttsplugin.TtsPlugin"));
}
}
Summary
Text To Speech をFlutterでやりたかったので実装してみましたが、MethodChannelを使用してプラットフォームにメッセージの送信してネイティブのコードを実行する実装だけ行い、ネイティブコードとFlutterとの連携なぎ込みなどはツールがよしなにやってくれたので割りと簡単に作成することができました。
作成したPluginはGitHubに公開中
granoeste/tts_plugin at develop