Flutter(MethodChannel/Android)

# MethodChannel
FlutterとAndroid or iOS間のやりとりを可能にするクラスです
Flutter側でメッセージを送信して、Android or iOS側でメッセージを受信して対応した処理の結果を返却する

# Flutter側
Flutter側のメッセージ送信手順を記載します

1. MethodChannelの実装(チャンネル名を指定します。プラットフォーム側で同じチャンネル名を指定する必要があります)
2. invokeMethodの実装
    1. 第1引数：プラットフォーム側でメソッドを識別するための文字列を指定
    1. 第2引数：プラットフォーム側に送りたいデータを指定。複数送る場合はMap型にすると良いらしいです

# プラットフォーム(Android)側
プラットフォーム側のメッセージ受信手順を記載します。今回はAndroidのみの記載になります 

1. MethodChannel.setMethodCallHandlerでメッセージを受信
2. MethodCallのmethod(Flutter側で指定した文字列)で処理の切り分けを行う
3. MethodChannel.ResultのsuccessでFlutter側に処理結果を返却


# Flutter側実装
```main.dart
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const platform = MethodChannel('samples.flutter.dev/testData');

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
              onPressed: _getValue,
              child: const Text('一番'),
            ),
            ElevatedButton(
              onPressed: _getValue2,
              child: const Text('二番'),
            ),
            Text(_result),
          ],
        ),
      ),
    );
  }

  String _result = 'Unknown Value';

  Future<void> _getValue() async {
    String result1;
    try {
      final int result = await platform.invokeMethod('getValue1');
      result1 = 'ネイティブから来ました $result 番です .';
    } on PlatformException catch (e) {
      result1 = "Failed to get value: '${e.message}'.";
    }

    setState(() {
      _result = result1;
    });
  }

  Future<void> _getValue2() async {
    String result1;
    try {
      final int result = await platform.invokeMethod('getValue2');
      result1 = 'ネイティブから来ました $result 番です .';
    } on PlatformException catch (e) {
      result1 = "Failed to get value: '${e.message}'.";
    }

    setState(() {
      _result = result1;
    });
  }
}

```

# プラットフォーム(Android)側実装
```MainActivity.kt
    class MainActivity: FlutterActivity() {
    private val CHANNEL = "samples.flutter.dev/testData"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
            // This method is invoked on the main thread.
                call, result ->
            if (call.method == "getValue1") {
                val value = 1
                result.success(value)

            }
            if(call.method == "getValue2"){
                val value = 2
                result.success(value)
            }
        }

    }


}
```

# 注意点
プラットフォーム側のsuccessで結果を返す場合型に注意する必要があります
例えば、プラットフォーム側のsuccessの引数にFloatを指定するとFlutter側ではDoubleで返ってきます


参考：


https://api.flutter.dev/javadoc/io/flutter/plugin/common/StandardMessageCodec.html

# まとめ
MethodChannelを使用したFlutterとAndroid間のやり取りを実現する方法について見てきました
思ったよりも簡単にAndroid側のメソッドを利用できて驚きました
書いている内容が間違っている・補足すべきなどのご意見ありましたらご教授いただけますと幸いです

# 参考サイト

https://api.flutter.dev/javadoc/io/flutter/plugin/common/MethodChannel.html


https://docs.flutter.dev/development/platform-integration/platform-channels?tab=type-mappings-kotlin-tab