flutter和Android原生通信共计有三种类型,分别是:
- MethodChannel:flutter和Android之间互相调用,调用一次,执行一次,如Flutter调用Native拍照
- EventChannel:用于数据流(event streams)的通信,持续通信,收到消息后无法回复此次消息,通常用于Native向Dart的通信,如:手机电量变化,网络连接变化,陀螺仪,传感器等;
- BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Dart,在比如:Flutter将从服务端陆陆续获取到信息交个Native加工,Native处理完返回等
这三种类型的类型的Channel都是通信,即A <=> B,Flutter可以主动发送消息给platform端,并且platform接收到消息后可以做出回应,同样,platform端可以主动发送消息给Flutter端,Flutter端接收数后返回给platform端。 这一篇主要记录一下MethodChannel的使用方法
Flutter代码通过MethodChannel调用Android代码
1、在fluttr代码中新建MethodChannel
class _MyHomePageState extends State<MyHomePage> {
String content = "";
//新建MethodChannel
MethodChannel _methodChannel = MethodChannel("methodChannel");
@override
void initState() {
// TODO: implement initState
super.initState();
print(window.defaultRouteName);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"$content",
),
RaisedButton(
onPressed: callNative,
child: Text("callNative_byMethodChanndel"),
),
],
),
),
);
}
void callNative() async {
_methodChannel.invokeMethod(
"callNative", {"arg1": "I am from Flutter"}).then((value) {
//Android收到调用之后返回的数据
setState(() {
content = value;
});
});
}
}
2、Android代码中继承FlutterActivity,新建MethodChannel并且设置监听
public class MyFlutterActivity extends FlutterActivity {
public final static String INIT_PARAMS = "initParams";
//METHOD_CHANNEL要和flutter中 MethodChannel _methodChannel = MethodChannel("methodChannel");的参数相同
public final static String METHOD_CHANNEL = "methodChannel";
private String initParams;
private MethodChannel methodChannel;
public static void start(Context context, String initParams) {
Intent intent = new Intent(context, MyFlutterActivity.class);
intent.putExtra(INIT_PARAMS, initParams);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initParams = getIntent().getStringExtra(INIT_PARAMS);
methodChannel = new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), METHOD_CHANNEL);
methodChannel.setMethodCallHandler((call, result) -> {
switch (call.method) {
case "callNative":
Toast.makeText(this, call.argument("arg1"), Toast.LENGTH_LONG).show();
result.success("我是来自Native的回调");
break;
}
});
}
/**
* 重载该方法来传递初始化参数
*
* @return
*/
@NonNull
@Override
public String getInitialRoute() {
return initParams == null ? super.getInitialRoute() : initParams;
}
}
然后是Android代码通过MethodChannel调用Flutter代码
1、创建Activity继承FlutterActivity,并创建MethodChannel
package com.example.nativeapp;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.StringCodec;
public class MyFlutterActivity extends FlutterActivity {
public final static String INIT_PARAMS = "initParams";
public final static String METHOD_CHANNEL = "methodChannel";
private String initParams;
private MethodChannel methodChannel;
public static void start(Context context, String initParams) {
Intent intent = new Intent(context, MyFlutterActivity.class);
intent.putExtra(INIT_PARAMS, initParams);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initParams = getIntent().getStringExtra(INIT_PARAMS);
methodChannel = new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), METHOD_CHANNEL);
methodChannel.invokeMethod("callFlutter", "agr1=666", new MethodChannel.Result() {
@Override
public void success(Object result) {
Log.i("tag",result.toString());
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
}
@Override
public void notImplemented() {
}
});
}
/**
* 重载该方法来传递初始化参数
*
* @return
*/
@NonNull
@Override
public String getInitialRoute() {
return initParams == null ? super.getInitialRoute() : initParams;
}
}
2、在Flutter代码中创建MethodChannel,并设置监听
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String content = "";
MethodChannel _methodChannel = MethodChannel("methodChannel");
@override
void initState() {
// TODO: implement initState
super.initState();
print(window.defaultRouteName);
//设置监听
_methodChannel.setMethodCallHandler(_methodChannelHandler);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"$content",
),
],
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
//方法是异步的
Future<String> _methodChannelHandler(MethodCall call) async {
String result = "";
switch (call.method) {
//收到Android的调用,并返回数据
case "callFlutter":
setState(() {
content = call.arguments.toString();
});
result = "收到来自Android的消息";
break;
}
return result;
}
}