Flutter项目WanWan之接入融云IM和自定义Plugin
Posted 白玉梁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter项目WanWan之接入融云IM和自定义Plugin相关的知识,希望对你有一定的参考价值。
项目地址 GitHub:https://github.com/baiyuliang/Flutter-WanWan
融云IM-Flutter文档地址:https://docs.rongcloud.cn/v4/5X/views/im/noui/guide/quick/include/flutter.html
集成步骤:
注意:需要先去融云官网注册账号,并创建应用,获取应用appid和appkey!
- 引入SDK:
rongcloud_im_plugin: ^5.1.3
- 初始化:
RongIMClient.init(Url.RONG_IM_KEY);
- 连接服务器:
RongIMClient.connect(token, (int code, String userId) {
if (code == 0) {
}
});
- 设置监听:
RongIMClient.onConnectionStatusChange = (int connectionStatus) {};
RongIMClient.onMessageReceived = (Message msg, int left) {};
- 获取会话列表:
RongIMClient.getConversationListByPage([
RCConversationType.Private,
RCConversationType.Group,
RCConversationType.System
], 999, 0);
- 发送消息:
TextMessage txtMessage = new TextMessage();
txtMessage.content = "";
txtMessage.extra = "";
Message msg = await RongIMClient.sendMessage(RCConversationType.Private, targetId, txtMessage);
消息有多种类型,具体可参考文档!
由于融云的登录,依赖于服务器生成的token,如要正常使用需要自己写后台,这对于完全移动端或前端开发者来说可能无法完成,那么重点来了,本项目中引入了服务端java的serverSDK,放在了android项目中libs,来模拟服务端的注册以及其它相关请求!
这里有一个技巧,我们在同时开发flutter端和native端(这里已android为例)时,可以分别打开flutter项目和flutter项目的android部分:
flutter:
android:
此时,我们就可以在android项目中,完成服务端相关功能,如注册方法:
val map = HashMap<String, Any>()
val id = call.argument<String>("id")!!.toString()
val name = call.argument<String>("name")!!.toString()
val avatar = call.argument<String>("avatar")!!.toString()
val user: User = rongCloud.user
val userModel = UserModel()
.setId(id)
.setName(name)
.setPortrait(avatar)
Thread {
try {
val tokenResult = user.register(userModel)
if (!TextUtils.isEmpty(tokenResult.token)) {
map["code"] = 200
map["token"] = tokenResult.token
map["error"] = "注册成功"
Log.e("RongIMRegPlugin", "注册成功: $tokenResult")
} else {
map["code"] = -1
map["error"] = "注册失败"
}
} catch (e: Exception) {
e.printStackTrace()
map["code"] = -1
map["error"] = e.message.toString()
}
activity.runOnUiThread {
result.success(map)
}
}.start()
那么问题又来了,如何实现flutter与本地通信?
教大家一个最简单的办法:https://www.baidu.com …此处省略一万字!
开个玩笑!其实很简单,要善于发现,比葫芦画瓢,相信我们在开发过程中,或多或少的引入了其他的第三方库,我们可以打开参观一下他们的Plugin.java,看实现过程,随便打开一个,以为SharedPreferences例:
/** SharedPreferencesPlugin */
public class SharedPreferencesPlugin implements FlutterPlugin {
private static final String CHANNEL_NAME = "plugins.flutter.io/shared_preferences";
private MethodChannel channel;
private MethodCallHandlerImpl handler;
@SuppressWarnings("deprecation")
public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
final SharedPreferencesPlugin plugin = new SharedPreferencesPlugin();
plugin.setupChannel(registrar.messenger(), registrar.context());
}
@Override
public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding binding) {
setupChannel(binding.getBinaryMessenger(), binding.getApplicationContext());
}
@Override
public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding binding) {
teardownChannel();
}
private void setupChannel(BinaryMessenger messenger, Context context) {
channel = new MethodChannel(messenger, CHANNEL_NAME);
handler = new MethodCallHandlerImpl(context);
channel.setMethodCallHandler(handler);
}
private void teardownChannel() {
handler.teardown();
handler = null;
channel.setMethodCallHandler(null);
channel = null;
}
}
显然,该类继承了FlutterPlugin,并重写了两个方法:onAttachedToEngine和onDetachedFromEngine,
在获取MethodChannel实例后:
channel = new MethodChannel(messenger, CHANNEL_NAME);
实现了MethodCallHandler接口,
handler = new MethodCallHandlerImpl(context);
channel.setMethodCallHandler(handler)
再来看MethodCallHandlerImpl:
class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
String key = call.argument("key");
try {
switch (call.method) {
case "setBool":
commitAsync(preferences.edit().putBoolean(key, (boolean) call.argument("value")), result);
break;
......
}
以上只贴了部分代码,流程已经很清楚了,比葫芦画瓢开始:
- 步骤一:创建RongIMServerPlugin,继承FlutterPlugin:
class RongIMServerPlugin() : FlutterPlugin{
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}
}
- 步骤二:获取MethodChannel实例:
private var channel: MethodChannel? = null
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(binding.binaryMessenger, "rongim/server")
}
注意,channel的name可以自定义,我将其定义为**“rongim/server”**,flutter在调用时要保持一致!
- 步骤三:实现MethodChannel.MethodCallHandler接口:
class RongIMServerPlugin() : FlutterPlugin, MethodChannel.MethodCallHandler {
private var channel: MethodChannel? = null
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(binding.binaryMessenger, "rongim/server")
channel!!.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel!!.setMethodCallHandler(null)
channel = null
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
}
}
其实我们并不一定要像SharedPreferences中一样,单独写一个MethodCallHandlerImpl类,我们可以像实现View.OnClickListener一样用setMethodCallHandler(this)直接在主类中实现!
- 步骤四:重写onMethodCall方法,并根据call.method方法名,判断不同调用方法,执行不同操作:
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"register" -> {
}
"user" -> {
}
}
}
如果,方法中需要用到context上下文,我们可以在构造方法中引入:
class RongIMServerPlugin(activity: Activity) : FlutterPlugin{
private var activity: Activity = activity
}
Plugin书写完毕后,在MainActivity中注册:
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
flutterEngine!!.plugins.add(RongIMServerPlugin(this))
}
}
如果你不明白为什么这么写,可以打开:
flutter端调用:
static Future<Map> register(String id, String name, String avatar) async {
var methodChannel = const MethodChannel("rongim/server");
Map<String, dynamic> params = <String, dynamic>{
"id": id,
"name": name,
"avatar": avatar
};
var result = await methodChannel.invokeMethod("register", params);
return result;
}
参数以map形式传递,android端onMethodCall方法接收参数:
val id = call.argument<String>("id")!!.toString()
val name = call.argument<String>("name")!!.toString()
val avatar = call.argument<String>("avatar")!!.toString()
详细代码,可参考项目:https://github.com/baiyuliang/Flutter-WanWan
以上是关于Flutter项目WanWan之接入融云IM和自定义Plugin的主要内容,如果未能解决你的问题,请参考以下文章