在使用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<String, dynamic> 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<ContentWidget>{ //初始化MethodChannel static const nativeChannel = const MethodChannel('com.example.flutter/native'); Widget build(BuildContext context) { // TODO: implement build return Center( child: Stack( children: <Widget>[ 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<String> returnLastNativePage(MethodChannel channel) async{ //参数 // const channel = const MethodChannel('com.example.flutter/native'); // static const flutterChannel = const MethodChannel('com.example.flutter/flutter'); Map<String, dynamic> 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的方式