Flutter即时通讯插件im_flutter_sdk的使用
Flutter即时通讯插件im_flutter_sdk的使用
通过本文可以实现一个集成聊天 SDK 的简单 app。
实现原理
发送和接收单聊消息的步骤如下:
- 客户端向你的应用服务器请求 Token,你的应用服务器返回 Token。
- 客户端 A 和客户端 B 使用获得的 Token 登录环信即时通讯系统。
- 客户端 A 发送消息到环信即时通讯服务器。
- 环信即时通讯服务器将消息发送到客户端 B,客户端 B 接收消息。
前提条件
- Xcode 12.4 或以上版本(iOS)
- iOS 10 或以上版本(iOS)
- Android SDK API 等级 21 或以上版本(Android)
- Android Studio 4.0 或以上版本,包括 JDK 1.8 或以上版本(Android)
- CocoaPods 包管理工具(iOS)
- Flutter 2.10 或以上版本
- Dart 2.16 或以上版本
- 有效的环信即时通讯 IM 开发者账号和 App Key
项目设置
使用命令创建项目
flutter create quick_start
设置 Android
打开文件 quick_start/android/app/build.gradle
在文件最后添加:
android {
defaultConfig {
minSdkVersion 21
}
}
在 quick_start/android/app/proguard-rules.pro
中设置免混淆规则:
-keep class com.hyphenate.** {*;}
-dontwarn com.hyphenate.**
设置 iOS
打开文件 quick_start/ios/Runner.xcodeproj
,然后:
- 找到
TARGETS > Runner
在General
的Deployment Info
中修改最低版本为iOS 10.0
集成 SDK
在终端命令行,输入命令添加依赖:
cd quick_start
flutter pub add im_flutter_sdk
flutter pub get
添加示例代码
打开 quick_start/lib/main.dart
文件,引入头文件:
import 'package:flutter/material.dart';
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
修改 _MyHomePageState
代码:
class _MyHomePageState extends State<MyHomePage> {
ScrollController scrollController = ScrollController();
String _username = "";
String _password = "";
String _messageContent = "";
String _chatId = "";
final List<String> _logText = [];
@override
void initState() {
super.initState();
_initSDK();
_addChatListener();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.max,
children: [
TextField(
decoration: const InputDecoration(hintText: "Enter username"),
onChanged: (username) => _username = username,
),
TextField(
decoration: const InputDecoration(hintText: "Enter password"),
onChanged: (password) => _password = password,
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 1,
child: TextButton(
onPressed: _signIn,
child: const Text("SIGN IN"),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Colors.lightBlue),
),
),
),
const SizedBox(width: 10),
Expanded(
child: TextButton(
onPressed: _signOut,
child: const Text("SIGN OUT"),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Colors.lightBlue),
),
),
),
const SizedBox(width: 10),
Expanded(
child: TextButton(
onPressed: _signUp,
child: const Text("SIGN UP"),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Colors.lightBlue),
),
),
),
],
),
const SizedBox(height: 10),
TextField(
decoration: const InputDecoration(
hintText: "Enter recipient's user name"),
onChanged: (chatId) => _chatId = chatId,
),
TextField(
decoration: const InputDecoration(hintText: "Enter message"),
onChanged: (msg) => _messageContent = msg,
),
const SizedBox(height: 10),
TextButton(
onPressed: _sendMessage,
child: const Text("SEND TEXT"),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor: MaterialStateProperty.all(Colors.lightBlue),
),
),
Flexible(
child: ListView.builder(
controller: scrollController,
itemBuilder: (_, index) {
return Text(_logText[index]);
},
itemCount: _logText.length,
),
),
],
),
),
);
}
void _initSDK() async {
EMOptions options = EMOptions(
appKey: "<#Your AppKey#>",
autoLogin: false,
);
await EMClient.getInstance.init(options);
await EMClient.getInstance.startCallback();
}
void _addChatListener() {
EMClient.getInstance.chatManager.addMessageEvent(
"UNIQUE_HANDLER_ID",
ChatMessageEvent(
onSuccess: (msgId, msg) {
_addLogToConsole("send message succeed");
},
onProgress: (msgId, progress) {
_addLogToConsole("send message succeed");
},
onError: (msgId, msg, error) {
_addLogToConsole(
"send message failed, code: ${error.code}, desc: ${error.description}",
);
},
));
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onMessagesReceived: (messages) {
for (var msg in messages) {
switch (msg.body.type) {
case MessageType.TXT:
{
EMTextMessageBody body = msg.body as EMTextMessageBody;
_addLogToConsole(
"receive text message: ${body.content}, from: ${msg.from}",
);
}
break;
// 其他类型的消息处理...
}
}
},
),
);
}
void _signIn() async {
if (_username.isEmpty || _password.isEmpty) {
_addLogToConsole("username or password is null");
return;
}
try {
await EMClient.getInstance.login(_username, _password);
_addLogToConsole("sign in succeed, username: $_username");
} on EMError catch (e) {
_addLogToConsole("sign in failed, e: ${e.code} , ${e.description}");
}
}
void _signOut() async {
try {
await EMClient.getInstance.logout(true);
_addLogToConsole("sign out succeed");
} on EMError catch (e) {
_addLogToConsole(
"sign out failed, code: ${e.code}, desc: ${e.description}");
}
}
void _signUp() async {
if (_username.isEmpty || _password.isEmpty) {
_addLogToConsole("username or password is null");
return;
}
try {
await EMClient.getInstance.createAccount(_username, _password);
_addLogToConsole("create account succeed, username: $_username");
} on EMError catch (e) {
_addLogToConsole(
"create account failed, code: ${e.code}, desc: ${e.description}");
}
}
void _sendMessage() async {
if (_chatId.isEmpty || _messageContent.isEmpty) {
_addLogToConsole("single chat id or message content is null");
return;
}
var msg = EMMessage.createTxtSendMessage(
targetId: _chatId,
content: _messageContent,
);
EMClient.getInstance.chatManager.sendMessage(msg);
}
void _addLogToConsole(String log) {
_logText.add(_timeString + ": " + log);
setState(() {
scrollController.jumpTo(scrollController.position.maxScrollExtent);
});
}
String get _timeString {
return DateTime.now().toString().split(".").first;
}
@override
void dispose() {
EMClient.getInstance.chatManager.removeMessageEvent("UNIQUE_HANDLER_ID");
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
super.dispose();
}
}
运行项目
以 iOS 为例,首先打开模拟器,之后在终端输入:
flutter run
更多关于Flutter即时通讯插件im_flutter_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter即时通讯插件im_flutter_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用im_flutter_sdk
插件进行即时通讯的基本示例代码。请注意,这只是一个基本的实现示例,具体的使用可能会根据im_flutter_sdk
的版本和即时通讯平台(如环信、融云等)的不同而有所差异。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加im_flutter_sdk
的依赖:
dependencies:
flutter:
sdk: flutter
im_flutter_sdk: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
2. 初始化SDK
在你的main.dart
文件中,初始化SDK并进行基本的配置。以下是一个示例:
import 'package:flutter/material.dart';
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
void main() {
// 初始化SDK
IMFlutterSDK.init({
"appKey": "你的AppKey", // 替换为你的AppKey
"serverHost": "你的服务器地址", // 替换为你的服务器地址
// 其他配置项,如是否启用调试模式等
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter IM Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: IMHomeScreen(),
);
}
}
class IMHomeScreen extends StatefulWidget {
@override
_IMHomeScreenState createState() => _IMHomeScreenState();
}
class _IMHomeScreenState extends State<IMHomeScreen> {
@override
void initState() {
super.initState();
// 可以在这里添加登录逻辑
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('IM Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('这里是IM首页'),
// 你可以添加按钮来触发发送消息、查看聊天列表等操作
ElevatedButton(
onPressed: () {
// 示例:发送消息
sendMessage("接收者ID", "Hello, this is a test message!");
},
child: Text('发送消息'),
),
],
),
),
);
}
void sendMessage(String toUserId, String content) {
// 发送消息的示例代码,具体实现需要参考im_flutter_sdk的文档
IMFlutterSDK.sendMessage({
"toUserId": toUserId,
"content": content,
"messageType": "text", // 根据需要设置消息类型,如文本、图片等
}).then((result) {
// 处理发送结果
print("发送结果: $result");
}).catchError((error) {
// 处理发送错误
print("发送错误: $error");
});
}
}
3. 处理回调和事件
为了处理即时通讯中的各种回调和事件(如收到新消息、用户登录状态变化等),你需要在适当的地方添加事件监听器。例如:
@override
void initState() {
super.initState();
// 添加收到新消息的监听器
IMFlutterSDK.addMessageListener((message) {
// 处理新消息
print("收到新消息: $message");
});
// 添加登录状态变化的监听器
IMFlutterSDK.addConnectionListener((status) {
// 处理登录状态变化
print("登录状态变化: $status");
});
// 可以在这里添加登录逻辑
IMFlutterSDK.login({
"userId": "你的用户ID",
"token": "你的登录Token", // 或者其他登录凭证
}).then((result) {
// 处理登录结果
print("登录结果: $result");
}).catchError((error) {
// 处理登录错误
print("登录错误: $error");
});
}
4. 清理资源
在适当的时机(如应用退出时),记得清理资源:
@override
void dispose() {
// 移除监听器
IMFlutterSDK.removeMessageListener(null); // 或者传入具体的监听器ID
IMFlutterSDK.removeConnectionListener(null); // 或者传入具体的监听器ID
// 注销登录(可选)
IMFlutterSDK.logout().then((result) {
// 处理注销结果
print("注销结果: $result");
}).catchError((error) {
// 处理注销错误
print("注销错误: $error");
});
super.dispose();
}
注意事项
- 依赖版本:确保你使用的
im_flutter_sdk
版本与你的即时通讯平台兼容。 - 文档:详细的功能和API使用方法请参考
im_flutter_sdk
的官方文档。 - 错误处理:在实际应用中,添加更详细的错误处理逻辑,以提高应用的健壮性。
- UI设计:根据实际需求,设计更符合用户习惯的UI界面。
以上示例代码仅用于演示如何在Flutter项目中使用im_flutter_sdk
插件进行基本的即时通讯功能。具体实现时,请根据你的即时通讯平台和业务需求进行调整。