LoginSignup
9
13

More than 3 years have passed since last update.

Flutter MessageChannel APIの使い方

Last updated at Posted at 2020-02-10

はじめに

Flutter (Dart) とプラットフォーム (Android/iOSなど) 間の通信/呼び出しAPIについてまとめています。

1. MessageChannelとは

プラットフォーム (Android/iOSなど) とFlutter (Dart) 間で双方向でメッセージ送受信するためのAPIであるMessageChannel (正確にはBasicMessageChannel) です。片方からもう片方にデータを送信し、受信したらリプライを返すというごく普通のメッセージパッシング用のAPIです。

Flutterの仕組み的には、ここで解説しているPlatform Channelsを利用しています。

2. 基本フロー

実際のコードの説明の前にAPIの基本的なフローについて解説します。
ただし、プラットフォーム毎に若干API名が異なる場合があるため (iOS) 、注意してください。

送信側

  1. BasicMessageChannelでチャンネル生成
  2. BasicMessageChannel#sendでデータ送信

受信側

  1. BasicMessageChannel#MessageHandlerでイベントリスナーを登録
  2. データ受信時に登録したイベントリスナーのBasicMessageChannel#MessageHandler#onMessageがコールバックされるため、その中でリプライデータを送信

Dart → プラットフォームへの送信

スクリーンショット 2020-02-09 19.48.31.png

プラットフォーム → Dartへの送信

スクリーンショット 2020-02-09 19.48.40.png

3. サンプルプロジェクト

実際のAPIの使い方は後述しますが、サンプルプロジェクトを以下に用意しています。そのまま動作確認可能ですので、参考にしてください。
ただし、正式に何かの機能を実装する場合にはプラグインの形で組み込んだ方が良いです。
https://github.com/Kurun-pan/flutter-messagechannel-example

4. Flutter + Android (Kotlin) のコード解説

4.1 Dart側の実装

通信チャンネル作成

MethodChannel同様、BasicMessageChannelの通信チャンネルを作成します。

API仕様
BasicMessageChannel(String name, MessageCodec<T> codec, {BinaryMessenger binaryMessenger})

第1引数には、指定する文字列は他のアプリケーションと被らず、一意に決まるようにするために慣例で"アプリパッケージ名/チャンネル名"とするのが一般的な様子です。

第2引数は送信データのコーデックタイプを指定します。Frameworkの内部的にはバイナリデータとして扱われるため、その情報を指定する必要があります。

タイプ 内容
BinaryCodec ByteDataのデータ送信時
JSONMessageCodec JSON形式のデータ送信時
StandardMessageCodec 通常はこちらを利用(プリミティブ型)
StringCodec Stringデータを送信時

なお、サンプルプロジェクト↓ではJSONMessageCodecを利用したデータ送信の例をコメントアウトした形で残していますので、参考にしてください。
https://github.com/Kurun-pan/flutter-messagechannel-example/blob/master/lib/main.dart

データ送信

BasicMessageChannel#sendでデータ送信

API仕様
Future<T> send(T message) async {
  return codec.decodeMessage(await binaryMessenger.send(name, codec.encodeMessage(message)));
}

サンプルコード

サンプルコードは、Dart側からプラットフォーム側に文字列 (String型) を送信&リプライ受信と、プラットフォーム側からのメッセージ受信&リプライ送信の双方向の内容を盛り込んでいます。

Dartサンプルコード
class _MyHomePageState extends State<MyHomePage> {
  static const _channel = BasicMessageChannel('com.example.messagechannel/interop', StringCodec());

  String _platformMessage;

  void _sendMessage() async {
    final String reply = await _channel.send('Hello World form Dart');
    print(reply);
  }

  @override
  initState() {
    super.initState();

    // Receive messages from platform
    _channel.setMessageHandler((String message) async {
      print('Received message = $message');
      setState(() => _platformMessage = message);
      return 'Reply from Dart';
    });

    // Send message to platform
    _sendMessage();
  }

4.2 プラットフォーム側の実装

通信チャンネル作成

BasicMessageChannelの通信チャンネルを作成します。

API仕様
BasicMessageChannel(BinaryMessenger messenger, String name, MessageCodec<T> codec)

第3引数にはString型のデータ送信時にはStringCodec.INSTANCEを指定します。StringCodecのstaticインスタンスになり、ソースコードを見てもらった方が早いです。

受信待機

BasicMessageChannel#setMessageHandlerでイベントリスナーを登録します。

リプライ送信

データ受信時に登録したイベントリスナーのBasicMessageChannel#MessageHandler#onMessageがコールバックされるため、その中でリプライデータを送信します。

サンプルコード

サンプルコードは、プラットフォーム側からプラットフォーム側に文字列 (String型) を送信&リプライ受信と、Dart側からのメッセージ受信&リプライ送信の双方向の内容を盛り込んでいます。

Kotlinサンプルコード
class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        val channel = BasicMessageChannel(
                flutterEngine.dartExecutor.binaryMessenger,
                "com.example.messagechannel/interop",
                StringCodec.INSTANCE)

        // Receive messages from Dart
        channel.setMessageHandler { message, reply ->
            Log.d("Android", "Received message = $message")
            reply.reply("Reply from Android")
        }

        // Send message to Dart
        Handler().postDelayed({
            channel.send("Hello World from Android") { reply ->
                Log.d("Android", "$reply")
            }
        }, 500)
    }
}
9
13
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
9
13