Android与Flutter之间的通信共有四种实现方式。
1.由于在初始化flutter页面时会传递一个字符串——route,因此我们就可以拿route来做文章,传递自己想要传递的数据。该种方式仅支持单向数据传递且数据类型只能为字符串,无返回值。
2.通过EventChannel来实现,EventChannel仅支持数据单向传递,无返回值。
3.通过MethodChannel来实现,MethodChannel支持数据双向传递,有返回值。
4.通过BasicMessageChannel来实现,BasicMessageChannel支持数据双向传递,有返回值。
本文采用的是MethodChannel方式,如要看其他三种请直接移动到文章底部
1 首先我们要在Android中定义插件
class FlutterPluginTestNewPlugin(
private val activity: Activity) : MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "download") {
Log.e("onMethodCall", call.method)
result.success("Android")
download()
} else if(call.method=="play") {
val intent = Intent(activity, DownloadPlayActivity::class.java)
intent.putExtra("proxy_url", MainActivity.item.proxyUrl)
intent.putExtra("origin_url", MainActivity.item.url)
activity.startActivity(intent)
}else{
result.notImplemented()
}
}
companion object {
private var channel: MethodChannel? = null
/// 保留旧版本的兼容
fun registerWith(registry: PluginRegistry) {
val registrar: PluginRegistry.Registrar = registry.registrarFor("flutter_plugin_test_new")
channel = MethodChannel(registrar.messenger(), "flutter_plugin_test_new")
channel!!.setMethodCallHandler(FlutterPluginTestNewPlugin(registrar.activity()))
}
}
private fun download(){
if (MainActivity.item.isRunningTask) {
LogUtils.d("jeffmony pause downloading.")
VideoDownloadManager.getInstance().pauseDownloadTask(MainActivity.item)
} else if (MainActivity.item.isSlientTask) {
LogUtils.d("jeffmony start downloading.")
VideoDownloadManager.getInstance().startDownload(MainActivity.item)
}
}
}
我定义了两个flutter调用Android的方法 download ,play
2 Android 插件注册
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this@MainActivity)
FlutterPluginTestNewPlugin.registerWith(this@MainActivity)
}
3 Flutter 调用原生插件
const platform = const MethodChannel('flutter_plugin_test_new');
final String result = await platform.invokeMethod('download');
需要注意的是 方法名要一致,(方法支持带参数),要有共同的Channel flutter_plugin_test_new (自己定义代表一个事件的tag)
简单提一下带参数的调用:
Flutter端发起
Map map = {"url": “123456”};
platform.invokeMethod('download',map);
Android端接收
val url: String? = call.argument("url")
1Android 定义插件
class MyFlutterEventPlugin implements EventChannel.StreamHandler {
public static EventChannel.EventSink eventSink;
public static MyFlutterEventPlugin registerWith(PluginRegistry registry) {
String CHANNEL = "event_plugin";
PluginRegistry.Registrar registrar = registry.registrarFor(CHANNEL);
EventChannel eventChannel = new EventChannel(registrar.messenger(), CHANNEL);
MyFlutterEventPlugin myFlutterEventPlugin = new MyFlutterEventPlugin();
eventChannel.setStreamHandler(myFlutterEventPlugin);
return myFlutterEventPlugin;
}
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
}
@Override
public void onCancel(Object o) {
}
}
2.Android 插件注册 & 调用
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
MyFlutterEventPlugin.registerWith(this)
MyFlutterEventPlugin eventPlugin = MyFlutterEventPlugin.registerWith(this);
// 成功的回调
MyFlutterEventPlugin.eventSink!!.success(“6666”)
//失败回调
// MyFlutterEventPlugin.eventSink!!.error("计时器异常", "计时器异常", e.message)
}
}
3.Flutter 注册监听器接收来自原生的消息
const myEventPlugin = const EventChannel('event_plugin');
@override
void initState() {
super.initState();
//设置监听
myEventPlugin.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}
void _onEvent(Object event) {
// 这里的event事Object类型 可以接收各种类型的参数
print("onEvent: $event");
}
void _onError(Object error) {
print("onError: $error");
}
温馨提示:
本文涉及到Flutter中Android插件的开发以及引用,不熟悉的同学请前往https://www.jianshu.com/p/4a9b6bf43b38学习如何构建插件,再看本文会得心应手。
本文基于Flutter 1.12之前,1.12之后插件写法可以沿用这种(已兼容),也可以进行升级,升级注意事项请前往https://blog.csdn.net/ZuoYueLiang/article/details/103706627
Flutter与原生交互总结
https://www.jianshu.com/p/f35da4195df9