在使用MethodChannel的时候也需要分几种情形,不同情形处理的细节不太一样。
第一种情形,假设先启动一个普通的MainActivity,然后再点击按钮,启动一个默认FlutterActivity的
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.view.FlutterMain;
public class MainActivity extends AppCompatActivity {
private static final String CHANNEL_NATIVE = "com.example.flutter/native";
private static final String CHANNEL_FLUTTER = "com.example.flutter/flutter";
@Override
protected void onCreate(Bundle savedInstanceState) {
FlutterMain.startInitialization(getApplicationContext());
prepareFlutterEngine();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first_native);
Button btnOpen = findViewById(R.id.button001);
btnOpen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(
// FlutterActivity.createDefaultIntent(this)
FirstFlutterActivity
.withCachedEngine("my_engine_id")
.build(MainActivity.this)
);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
TextView textView = findViewById(R.id.textView001);
textView.setText(data.getStringExtra("message"));
}
}
void prepareFlutterEngine(){
// Instantiate a FlutterEngine.
FlutterEngine flutterEngine = new FlutterEngine(getApplication());
flutterEngine.getNavigationChannel().setInitialRoute("route1");
// // Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
// // Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
configureFlutterEngine(flutterEngine);
}
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
Log.d("FirstNativeActivity","configureFlutterEngine");
GeneratedPluginRegistrant.registerWith(flutterEngine);//重要,注册plugin,如果不注册,可能会无法正常通信
MethodChannel mc = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL_NATIVE); //此处名称应与Flutter端保持一致
mc.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
switch (call.method){
case "backAction":
Log.d("ldw","flutter 页面中 backAction被触发");
onBackPressed();
result.success("成功通过虚拟按键返回第一个原生页面");
break;
default :
Log.d("ldw","notImplemented");
result.notImplemented();
break;
}
}
});
}
}
然后在flutter中需要写一下点击事件,通过handler传递给MainActivity来处理
void main() => runApp(_widgetForRoute(window.defaultRouteName));
Widget _widgetForRoute(String url) {
// route名称
String route ="默认";
route = url.indexOf('?') == -1 ? url : url.substring(0, url.indexOf('?'));
print('defaultRouteName:$url');
// 参数Json字符串
String paramsJson =
url.indexOf('?') == -1 ? '{}' : url.substring(url.indexOf('?') + 1);
Map mapJson = json.decode(paramsJson);
String message = "默认message";
message = mapJson["message"];
// 解析参数
switch (route) {
case 'route1':
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter页面'),
),
body: ContentWidget(route: route,message: message,),
),
);
default:
return Center(
child: Text('sorry Unknown route: $route',style: TextStyle(color: Colors.red), textDirection: TextDirection.ltr),
);
}
}
class ContentWidget extends StatefulWidget{
ContentWidget({Key key, this.route,this.message}) : super(key: key);
String route,message;
_ContentWidgetState createState() => new _ContentWidgetState();
}
class _ContentWidgetState extends State{
//初始化MethodChannel
static const nativeChannel = const MethodChannel('com.example.flutter/native');
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Stack(
children: [
Positioned(
top: 100,
left: 0,
right: 0,
height: 100,
child: Text(widget.message,textAlign: TextAlign.center,),
),
Positioned(
top: 200,
left: 100,
right: 100,
height: 100,
child: RaisedButton(
child: Text('打开上一个原生页面'),
onPressed: (){
//触发
returnLastNativePage(nativeChannel);
}
),
),
],
),
);
}
}
Future returnLastNativePage(MethodChannel channel) async{
//参数
// const channel = const MethodChannel('com.example.flutter/native');
// static const flutterChannel = const MethodChannel('com.example.flutter/flutter');
Map para = {'message':'嗨,本文案来自Flutter页面,回到第一个原生页面将看到我'};
final String result = await channel.invokeMethod('backAction',para);
print('这是在flutter中打印的'+ result);
}
第二种情形,启动的第一个MainActivity便是flutter的入口,继承自FlutterActivity,那么只要在MainActivity中重写即可
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodChannel
class MainActivity extends FlutterActivity() {
@override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
Log.d("FirstNativeActivity","configureFlutterEngine");
MethodChannel mc = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL_NATIVE); //此处名称应与Flutter端保持一致
mc.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
switch (call.method){
case "backAction":
Log.d("ldw","backAction");
onBackPressed();
result.success("成功通过虚拟按键返回第一个原生页面");
break;
default :
Log.d("ldw","notImplemented");
result.notImplemented();
break;
}
}
});
}
}
然后再flutter中触发backAction等事件即可
第三种情形,假设先启动一个普通的MainAcitivity,然后再点击按钮,启动一个自定义的FlutterActivity的,比如叫FirstFlutterActivity,且要指定一个route页面
则可以这么写
import android.util.Log;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class FirstFlutterActivity extends FlutterActivity {
private static final String CHANNEL_NATIVE = "com.example.flutter/native";
private static final String CHANNEL_FLUTTER = "com.example.flutter/flutter";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
Log.d("ldw","configureFlutterEngine:"+flutterEngine.toString());
super.configureFlutterEngine(flutterEngine);
FlutterEngineCache.getInstance().put("my_engine_id",flutterEngine);
MethodChannel mc = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL_NATIVE); //此处名称应与Flutter端保持一致
mc.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
switch (call.method){
case "backAction":
finish();
result.success("成功通过虚拟按键返回第一个原生页面");
break;
default :
result.notImplemented();
break;
}
}
});
}
}
然后在MainActivity中启动这个自定义的FirstFlutterActivity
Button btnOpen = findViewById(R.id.button001);
btnOpen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstNativeActivity.this,FirstFlutterActivity.class);
intent.putExtra("message","嗨,我是测试内容");//表示指定打开哪个route,传递给FlutterActivity使用
intent.putExtra("route","route1?{\"message\":\"" + "我是测试内容" + "\"}");
startActivityForResult(intent, Activity.RESULT_FIRST_USER);
}
});
其中
intent.putExtra("message","嗨,我是测试内容");
是指定了要打开的页面,不传这个值,会打开默认的route 即 "/"
不过改方式是通过阅读源码,看到源码中是这么使用的,在第三种方式中,我还没找到更好的打开指定route的方式