Agora Flutter SDK:一套代码,实现双端通话(三)

阅读数:24 2019 年 11 月 30 日 15:04

Agora Flutter SDK:一套代码,实现双端通话(三)

2 Flutter 和 Native 的交互

我们这里说的 Native 指的是 Android 平台。

那既然要相互通信,就需要将 Flutter 集成到 Android 工程中来,不清楚的如何集成可以看看这里

这里有一点需要注意,就是我们在 Android 代码中需要初始化 Dart VM,不然我们在使用 getFlutterView() 来获取一个 Flutter View 的时候会抛出如下异常:

复制代码
Caused by: java.lang.IllegalStateException: ensureInitializationComplete must be called after startInitialization
at io.flutter.view.FlutterMain.ensureInitializationComplete(FlutterMain.java:178)
...

我们有两种方式来执行初始化操作:一个是直接让我们的 Application 继承 FlutterApplication,另外一个是需要我们在我们自己的 Application 中手动初始化:

方法一:

复制代码
public class App extends FlutterApplication {
}

方法二:

复制代码
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化 Flutter
Flutter.startInitialization(this);
}
}

其实方法一中的 FlutterApplication 中在其 onCreate() 方法中干了同样的事情,部分代码如下:

复制代码
public class FlutterApplication extends Application {
...
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
...
}

如果我们的 App 只是需要使用 Flutter 在屏幕上绘制 UI,那么没问题, Flutter 框架能够独立完成这些事情。但是在实际的开发中,难免会需要调用 Native 的功能,如:定位,相机,电池等等。这个时候就需要 Flutter 和 Native 通信了。

官网上有一个案例是使用 MethodChannel 来调用给本地的方法获取手机电量。

其实我们还可以使用另外一个类进行通信,叫做 BasicMessageChannel,先来看看它如果创建:

复制代码
// java
basicMessageChannel = new BasicMessageChannel<String>(getFlutterView(), "foo", StringCodec.INSTANCE);

BasicMessageChannel 需要三个参数,第一个是 BinaryMessenger;第二个是通道名称,第三个是交互数据类型的编解码器,我们接下来的例子中的交互数据类型为 String ,所以这里传递的是 StringCodec.INSTANCE,Flutter 中还有其他类型的编解码器 BinaryCodec,JSONMessageCodec 等,他们都有一个共同的父类 MessageCodec。 所以我们也可以根据规则创建自己编解码器。

接下来创建的例子是:Flutter 给 Android 发送一条消息,Android 收到消息之后给 Flutter 回复一条消息,反之亦然。

先来看看 Android 端的部分代码:

复制代码
// 接收 Flutter 发送的消息
basicMessageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() {
@Override
public void onMessage(final String s, final BasicMessageChannel.Reply<String> reply) {
// 接收到的消息
linearMessageContainer.addView(buildMessage(s, true));
scrollToBottom();
// 延迟 500ms 回复
flutterContainer.postDelayed(new Runnable() {
@Override
public void run() {
// 回复 Flutter
String replyMsg = "Android : " + new Random().nextInt(100);
linearMessageContainer.addView(buildMessage(replyMsg, false));
scrollToBottom();
// 回复
reply.reply(replyMsg);
}
}, 500);
}
}); // ----------------------------------------------
// 向 Flutter 发送消息
basicMessageChannel.send(message, new BasicMessageChannel.Reply<String>() {
@Override
public void reply(final String s) {
linearMessageContainer.postDelayed(new Runnable() {
@Override
public void run() {
// Flutter 的回复
linearMessageContainer.addView(buildMessage(s, true));
scrollToBottom();
}
}, 500);
}
});

类似的,Flutter 这边的部分代码如下:

复制代码
// 消息通道
static const BasicMessageChannel<String> channel =
BasicMessageChannel<String>('foo', StringCodec());
// ----------------------------------------------
// 接收 Android 发送过来的消息,并且回复
channel.setMessageHandler((String message) async { String replyMessage = 'Flutter: ${Random().nextInt(100)}';
setState(() {
// 收到的 android 端的消息
_messageWidgets.add(_buildMessageWidget(message, true));
_scrollToBottom();
});
Future.delayed(const Duration(milliseconds: 500), () {
setState(() {
// 回复给 android 端的消息
_messageWidgets.add(_buildMessageWidget(replyMessage, false));
_scrollToBottom();
});
});
// 回复
return replyMessage;
});
// ----------------------------------------------
// 向 Android 发送消息
void _sendMessageToAndroid(String message) {
setState(() {
_messageWidgets.add(_buildMessageWidget(message, false));
_scrollToBottom();
});
// 向 Android 端发送发送消息并处理 Android 端给的回复
channel.send(message).then((value) {
setState(() {
_messageWidgets.add(_buildMessageWidget(value, true));
_scrollToBottom();
});
});
}

最后的效果如下:屏幕的上半部分为 Android,下半部分为 Flutter

Agora Flutter SDK:一套代码,实现双端通话(三)

如有问题,欢迎交流,谢谢!

源码地址:
https://github.com/liusilong/FlutterRendering
https://github.com/liusilong/FlutterAndroidCommunicate

本文转载自公众号声网 Agora(ID:shengwang-agora)。

原文链接:

https://mp.weixin.qq.com/s/hawD7myykCkVJbDbpRZHMw

评论

发布