LoginSignup
6

More than 3 years have passed since last update.

FlutterからKotlinの処理を呼ぶ

Last updated at Posted at 2019-03-08

はじめに

どうしてもFlutterを書いているとDartだけで表現できないこともおきてくるので、各ネイティブ処理呼べたらなーと思ってました。わざわざFlutterのプロジェクトを生成するときに各OSのフォルダあるしできるやろと思って調べたらやっぱりありました。

ここに書いてあることはplatform-channels全部書いてあったりしますが、その点はご了承ください。

iOSの環境作成をずっと面倒くさがってAndroidの話だけしか書いてません。

環境

Flutter 1.0
Android Studio

Dart側の対応

まず必要なパッケージをimportします。

import 'package:flutter/services.dart';

そしてメンバ変数としてMethodChannelを宣言しておきます。
引数は後々使うので、分かりやすい名前にしておきましょう。(以下チャンネル名と書きます。)

static const platform = const MethodChannel('com.tasogarei.test/web');

次に呼び出し口です。
わざわざ処理を呼び出したいので、たいていは状態変化させる箇所に書くことになるかと思います。
今回は読んだ先の日付を文字列でもらってsetStateする感じにします。

ここから呼び出しますが、呼び出し方は簡単でplatform.invokeMethod('web')とするだけです。
引数は識別子になりますので、これもわかるようにしておいてください。

  void _incrementCounter() async {
    String dateString = await platform.invokeMethod('web');
    setState(() {
      _title = dateString;
    });
  }

Kotlin側の対応

まずはFlutter作成時のbuild.gradleとかに書いてあるバージョンは基本的に古いので、いい感じに修正する必要があります。(ここでは割愛)

まずはKotlin側のソースを全部のせておきます。

package com.tasogarei.flutterapp2

import android.os.Bundle

import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import java.time.LocalDateTime

class MainActivity: FlutterActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      GeneratedPluginRegistrant.registerWith(this)

      MethodChannel(flutterView, "com.tasogarei.test/web").setMethodCallHandler { call, result ->
          when(call.method) {
              "web" -> {
                  result.success(LocalDateTime.now().toString())
              }
          }
      }
  }
}

今回肝となるコードはその中でこの部分になります。

      MethodChannel(flutterView, "com.tasogarei.test/web").setMethodCallHandler { call, result ->
          when(call.method) {
              "web" -> {
                  result.success(LocalDateTime.now().toString())
              }
          }
      }

ここで先ほどDartファイル側で設定しておいたチャンネル名と識別子が設定されます。
MethodChannelの第二引数にチャンネル名を渡すことで大元を識別し、そのCallHandler内で識別子を判定して処理させていきます。
Kotlin側からDart側へ結果を戻す際にはresult内に結果を詰め込むためのメソッドが用意されているので、それに結果を入れてあげるだけです。

resultの型はデータクラスではPlatformException(error, Unsupported value: Data(id=1, name=name), null)と出てダメだったので、文字列とか数字じゃないとダメそうです。
複雑なデータの場合はJson使用してやり取りするしか現状はなさそうです。

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
6