Flutter 和 Android 的交互网上的博文非常多,包括Flutter中文网上面关于MethodChannel 的内容,都已经过时了。比如Fluter 中文网上面写道的Android客户端集成如下:
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "samples.flutter.io/battery";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
// TODO
}
});
}
}
上面集成的是 io.flutter.app.FlutterActivity,通过 getFlutterView() 和 字符串来 构造 MethodChannel ,然后设置来自于 Flutter 调用的监听。
现在我们集成新的 Flutter SDK ,继承的Activity是 io.flutter.embedding.android.FlutterActivity,此FlutterActivity已经不存在 getFlutterView()
方法了,所以Android 和 Flutter的交互也要改变。
集成的流程如下:
1.Android 客户端的代码如下:
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
public class FlutterAppActivity extends FlutterActivity {
private final static String CHANNEL_NATIVE = "com.zhujiangtao.flutter";
private MethodChannel mMethodChannel;
public static void enter(Context context) {
Intent intent = new NewEngineIntentBuilder(FlutterAppActivity.class)
.initialRoute("zhujiangtao?msg=test&id=10010")
.build(context);
context.startActivity(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化 MethodChannel
mMethodChannel = new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), CHANNEL_NATIVE);
// Flutter 调用 android 的方法会执行到此回调
mMethodChannel.setMethodCallHandler((call, result) -> {
Log.e("xxxxx", "method = " + call.method);
switch (call.method) {
case "callNative":
Toast.makeText(FlutterAppActivity.this, call.argument("arg1"), Toast.LENGTH_LONG).show();
callFlutter();
// 将结果回调给 Flutter
result.success("我是来自Native的回调");
break;
}
});
}
private void callFlutter() {
// Android 端调用 Flutter 的方法
mMethodChannel.invokeMethod("callFlutter", "name=zhujiangtao", new MethodChannel.Result() {
@Override
public void success(@Nullable Object result) { // Flutter 回调过来的结果
if (result != null) {
Toast.makeText(FlutterAppActivity.this, result.toString(), Toast.LENGTH_LONG).show();
}
}
@Override
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
}
@Override
public void notImplemented() {
}
});
}
}
里面清晰的注释了,Android 是如何调用 Flutter 和 Flutter 是怎么调用Android的。
2. AndroidManifest.xml 中注册且处理跳转到Flutter页面黑屏问题
<!--就是之前写的Activity-->
<activity android:name=".ui.FlutterAppActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<!--解决android进入Flutter的黑屏问题-->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/flutter_splash_bg" />
</activity>
3. Flutter 端的代码调用原生方法和原生调用Flutter的回调
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:my_flutter/pages/list_view.dart';
class MyMethodChannel extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return MyMethodState();
}
}
class MyMethodState extends State<MyMethodChannel>{
String _content;
// 这里面的 “com.zhujiangtao.flutter”要和 Java 代码中 初始化 MethodChannel的值保持一致
static MethodChannel _methodChannel = MethodChannel('com.zhujiangtao.flutter');
@override
void initState() {
_methodChannel.setMethodCallHandler(_methodChannelHandler);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TestMethodChannel"),),
body: Center(
child: Column(
children: <Widget>[
Text('$_content'),
RaisedButton(
onPressed: callNative,
child: Text("callNative"),
),
RaisedButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => TestListView()));
},
child: Text('ListView'),
),
],
),
),
);
}
/// Flutter 调用原生
Future<void> callNative() async {
print("----------------callNative--------------------");
var res = await _methodChannel.invokeMethod("callNative", {"arg1": "I am from Flutter"});
//Android收到调用之后返回的数据
setState(() {
_content = res;
});
}
/// 原生 调用 Flutter的结果回调
Future<String> _methodChannelHandler(MethodCall call) async{
String result = "";
print("---------------_methodChannelHandler------------------------ method = ${call.method}");
switch(call.method){
case "callFlutter":
setState(() {
_content = call.arguments.toString();
});
result = "Flutter 收到 Android发来的消息";
break;
}
return result;
}
}
里面也是 初始化 MethodChannel ,然后逻辑和原生的差不多;
invokeMethod :原生和Flutter都是调用此方法来和对方通信;
setMethodCallHandler:都是结果的回调。
以上就是 Flutter 和 原生 的交互过程。