RN系列:Android原生与Flutter的交互与通信

一、flutter项目与android之间的交互

1.flutter调用android中的方法

bridge.dart

//toAndroid  是定义好的通道名称
 
static final _android = MethodChannel('toAndroid');
 
static void invokeAndroidPay(requestMsg) async{
 
  //pay是android代码中定义的方法
 
  var result=await _android.invokeMethod('pay',requestMsg);
 
}

MainActivity.kt

class MainActivity: FlutterActivity() {
 
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
 
        super.configureFlutterEngine(flutterEngine)
 
        GeneratedPluginRegistrant.registerWith(flutterEngine)
 
        val _android:MethodChannel=MethodChannel(flutterEngine.dartExecutor.binaryMessenger,"toAndroid")
 
        _android.setMethodCallHandler { call, result -> {
 
            if(call.method!=null){
 
                if ("pay".equals(call.method)){
 
                    result.success(pay())
 
                }
 
            }else {
 
                result.notImplemented()
 
            }
 
        }
 
        }
    }
 
    fun pay():String{
 
        return "success"
 
    }
 
}
2.Android调用Flutter中的方法

MainActivity中

lateinit var toFlutter: MethodChannel
 
//configureFlutterEngine方法中添加
 
toFlutter = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "toFlutter");
 
//调用
 
toFlutter.invokeMethod("shopSuccess", "", object : MethodChannel.Result {
 
    override fun success(o: Any?) {}
 
    override fun error(s: String, s1: String?, o: Any?) {}
 
    override fun notImplemented() {}
 
})

Flutter中

static final platform = MethodChannel('toFlutter');
 
platform.setMethodCallHandler(flutterMethod);
 
Future<dynamic> flutterMethod(MethodCall methodCall) async{
 
  switch (methodCall.method) {
    case 'shopSuccess':
      //TODO 要处理的方法
      break;
  }
}

二、Android原生项目与flutter module之间的交互

android项目依赖flutter module的方式网上有很多,这里就不做讲解。主要说一下这种情况下android如何与flutter module之间进行方法的调用

踩坑:期初我是想让flutter module调用它内部中的.android文件夹下的原生代码。.android文件夹下有Flutter、app、src文件夹,我都尝试在里面写了上述提到的交互方式,发现并没有什么用。

然后我在Android原生项目里面写了上述提到的交互方式发现还是没有作用。

原因:

1.flutter module内只能写dart语言,也就是只能在lib文件夹下操作,不能在module里面写原生代码

2.Android原生项目启动flutter 的时候使用的方法

FlutterActivity.createDefaultIntent(this)

总结:

Android原生项目启动flutter使用的是FlutterEngine,要想后面可以和flutter module交互,

以下两个方法中使用的flutterEngine必须和启动flutter module使用的一样。

GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine)
val _android: MethodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger,"toAndroid")

所以上代码注册引擎放到缓存中,以免每次启动flutter module的时候响应慢

 fun registerEngine(routerName: String,context: Context) {
        val engine = FlutterEngine(context)
        engine.navigationChannel.setInitialRoute(routerName)
        engine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
        FlutterEngineCache.getInstance().put(routerName,engine)
    }

 获取引擎

 fun getEngine(routerName: String):FlutterEngine?{
        return FlutterEngineCache.getInstance().get(routerName)
    }

启动flutter module

startActivity(FlutterActivity.withCachedEngine(routerName).build(this@MainActivity))

MainActivity继承flutterActivity并且设置交互方法

 val flutterEngine=EngineManager.getEngine(routerName)//获取引擎
        if (flutterEngine != null) {
            GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine)
            val _android: MethodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger,"toAndroid")
            _android.setMethodCallHandler { call, result ->
                if (call.method != null) {
                    if ("mymethod".equals(call.method)) {
                        mymethod()
                    }
 
                } else {
                    result.notImplemented()
 
                }
            }
        }

routerName我这里用的是flutter module里面设置的routers

三、如果想在flutter module中调用原生方法该怎么办?

我的想法是给flutter module中添加一个flutter插件,这样flutter module调用插件中的dart方法,然后插件去调用插件中的原生方法。

如何创建flutter 插件的方法网上有很多,这里说一下flutter module使用此插件的方法是在module下创建一个plugins文件夹,然后把插件的整个文件夹复制到plugins文件夹下面,然后再在flutter module的yaml文件里配置一下依赖,这样path路径就好写了