上云无忧 > 文档中心 > 环信IM即时通讯使用教程(Flutter) - 快速开始
IM即时通讯
环信IM即时通讯使用教程(Flutter) - 快速开始

文档简介:
通过本文可以实现一个集成聊天 SDK 的简单 app。 实现原理: 下图展示在客户端发送和接收一对一文本消息的工作流程。 如上图所示,发送和接收单聊消息的步骤如下: 客户端向你的应用服务器请求 Token,你的应用服务器返回 Token。 客户端 A 和客户端 B 使用获得的 Token 登录环信即时通讯系统。 客户端 A 发送消息到环信即时通讯服务器。 环信即时通讯服务器将消息发送到客户端 B,客户端 B 接收消息。
*此产品及展示信息均由环信官方提供。免费试用 咨询热线:400-826-7010,为您提供专业的售前咨询,让您快速了解云产品,助您轻松上云! 微信咨询
  免费试用、价格特惠

通过本文可以实现一个集成聊天 SDK 的简单 app。

实现原理

下图展示在客户端发送和接收一对一文本消息的工作流程。

如上图所示,发送和接收单聊消息的步骤如下:

  1. 客户端向你的应用服务器请求 Token,你的应用服务器返回 Token。
  2. 客户端 A 和客户端 B 使用获得的 Token 登录环信即时通讯系统。
  3. 客户端 A 发送消息到环信即时通讯服务器。
  4. 环信即时通讯服务器将消息发送到客户端 B,客户端 B 接收消息。

前提条件

开始前,请确保你的开发环境满足如下要求:

  • Xcode 12.4 或以上版本,包括命令行工具;
  • iOS 10 或以上版本;
  • Android SDK API 等级 21 或以上版本;
  • Android Studio 4.0 或以上版本,包括 JDK 1.8 或以上版本;
  • CocoaPods 包管理工具;
  • Flutter 2.10 或以上版本;
  • Dart 2.16 或以上版本;

配置开发或者运行环境如果遇到问题,请参考 这里 (opens new window)

  • 有效的环信即时通讯 IM 开发者账号和 App Key,详见 环信即时通讯云控制台 (opens new window)

项目设置

使用命令创建项目

打开终端,进入需要创建项目的目录,输入命令进行 flutter create 项目创建:

flutter create quick_start
 

设置 Android

  1. 打开文件 quick_start/android/app/build.gradle 在文件最后添加:
android {
    defaultConfig {
        minSdkVersion 21
    }
}
 
  1. 打开文件 quick_start/android/app/src/main/AndroidManifest.xml,在 </application> 下添加:

<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="
android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> 
 

  1. 在 quick_start/android/app/proguard-rules.pro 中设置免混淆规则:
-keep class com.hyphenate.** {*;} -dontwarn  com.hyphenate.** 
 

设置 iOS

iOS 需要 iOS 10.0 以上版本,

打开文件 quick_start/ios/Runner.xcodeproj,修改:TARGETS -> 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 = [];  void initState() { super.initState(); _initSDK(); _addChatListener
(); }  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 the 
username you want to send"), onChanged: (chatId) => _chatId = chatId, ), TextField( decoration: 
const InputDecoration(hintText: "Enter content"), 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 { } void _addChatListener() { } void _signIn()
 async { } void _signOut() async { } void _signUp() async { } void _sendMessage() async { } void 
_addLogToConsole(String log) { _logText.add(_timeString + ": " + log); setState(() { scrollController.
jumpTo(scrollController.position.maxScrollExtent); }); } String get _timeString 
{ return DateTime.now().toString().split(".").first; } } 
 

初始化 SDK

在 _initSDK 方法中添加 SDK 初始化:

void _initSDK() async { EMOptions options = EMOptions( appKey: "<#Your AppKey#>", autoLogin: false, );
 await EMClient.getInstance.init(options); // 通知 SDK UI 已准备好。该方法执行后才会收到 `EMChatRoomEventHandler
`、`EMContactEventHandler` 和 `EMGroupEventHandler` 回调。 await EMClient.getInstance.startCallback(); } 
 

注册环信 IM 用户

Demo 中使用 开放注册,此操作需要在环信后台开启 开放注册。在开放注册模式下,允许通过 App 客户端直接注册环信用户,正式环境中请使用 授权注册。

在 _signUp 方法中添加注册代码:

void _signUp() async { if (_username.isEmpty || _password.isEmpty) { _addLogToConsole("username or password is null")
; return; } try { await EMClient.getInstance.createAccount(_username, _password); _addLogToConsole("sign up succeed,
 username: $_username"); } on EMError catch (e) { _addLogToConsole("sign up failed, e: ${e.code} , ${e.description}"); } } 
 

添加登录

在 _signIn 方法中添加登录代码。

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}"); } } 
 

添加退出

在 _signOut 方法中添加退出代码。

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}"); } } 
 

添加发消息

在 _sendMessage 方法中添加发消息代码。

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); } 
 

添加收消息监听

在 _addChatListener 方法中添加代码。

void _addChatListener() { // 添加消息状态变更监听 EMClient.getInstance.chatManager.addMessageEvent
( // ChatMessageEvent 对应的 key。 "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.addEventHandle( // EMChatEventHandler 对应的 key。 "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; case MessageType.IMAGE: { _addLogToConsole( "receive 
image message, from: ${msg.from}", ); } break; case MessageType.VIDEO: { _addLogToConsole( "receive
 video message, from: ${msg.from}", ); } break; case MessageType.LOCATION: { _addLogToConsole( "receive 
location message, from: ${msg.from}", ); } break; case MessageType.VOICE: { _addLogToConsole( "receive
 voice message, from: ${msg.from}", ); } break; case MessageType.FILE: { _addLogToConsole( "receive 
image message, from: ${msg.from}", ); } break; case MessageType.CUSTOM: { _addLogToConsole
( "receive custom message, from: ${msg.from}", ); } break; case MessageType.CMD: { // 当前回调中不会有 
CMD 类型消息,CMD 类型消息通过 `EMChatEventHandler#onCmdMessagesReceived` 回调接收 } break; } } }, ), ); } 
 

移除消息监听

在 dispose 方法中添加代码移除监听:

 void dispose() { // 移除消息状态监听 EMClient.getInstance.chatManager.remove
MessageEvent("UNIQUE_HANDLER_ID"); // 移除收消息监听 EMClient.getInstance.chatManager.
removeEventHandle("UNIQUE_HANDLER_ID"); super.dispose(); } 
 

运行项目

以 iOS 为例,首先打开模拟器,然后在终端运行以下命令。

flutter run
 

运行结果如下:

参考以下步骤发送和接收文本消息:

  1. 输入任意用户名(如 flutter001 和 flutter002)和密码 1,点击 SIGN UP 创建用户;
  2. 以 flutter001 身份登录 Demo,将 Enter the username you want to send 输如为 flutter002, 发送文本消息;
  3. 以 flutter002 身份登录 Demo,查看 Log 信息确认是否都到消息。

后续步骤

为保障通信安全,在正式生产环境中,你需要在自己的 app 服务端生成 Token。详见使用 App Token 鉴权。

相似文档
  • 介绍 flutter 集成相关内容。 前提条件: 开始前,请注册有效的环信即时通讯 IM 开发者账号和取得 App key,见 环信即时通讯云管理后台 (opens new window)。 集成环境: 具体见 开发环境要求。
  • 4.0.0+4 修复: 安卓构建视频消息崩溃的问题。 4.0.0+3 修复: 安卓 onRemovedFromChatRoom 不回调。 4.0.0+2 修复: 修复List。 修复图片消息和视频消息转换失败;
  • 功能描述: 环信即时通讯 IM 支持多种消息类型,开发者可以方便地对本地会话、消息进行管理,可以从服务端获取历史会话和消息,提供送达回执和已读回执能力。
  • 登录即时通讯服务后,用户可以在单聊、群聊、聊天室中发送如下类型的消息: 文字消息,包含超链接和表情消息。 附件消息,包含图片、语音、视频及文件消息。 位置消息。 透传消息。 自定义消息。
  • 本文介绍环信即时通讯 IM Flutter SDK 如何管理本地消息数据。 除了发送和接收消息外,环信即时通讯 IM Flutter SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息以及查看或清空历史消息。
官方微信
联系客服
400-826-7010
7x24小时客服热线
分享
  • QQ好友
  • QQ空间
  • 微信
  • 微博
返回顶部