• Stars
    star
    237
  • Rank 169,080 (Top 4 %)
  • Language
    Dart
  • License
    MIT License
  • Created about 5 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

环信im flutter sdk, example中包含ui代码.

环信即时通讯 im_flutter_sdk 快速入门

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

实现原理

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

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

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

前提条件

如果你的目标平台是iOS,你需要满足一下要求:

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

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

项目设置

使用命令创建项目

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

flutter create quick_start

设置 Android

  1. 打开文件 quick_start/android/app/build.gradle 在文件最后添加:
android {
    defaultConfig {
        minSdkVersion 21
    }
}
  1. quick_start/android/app/proguard-rules.pro 中设置免混淆规则:
-keep class com.hyphenate.** {*;}
-dontwarn  com.hyphenate.**

设置 iOS

打开文件 quick_start/ios/Runner.xcodeproj,然后:

  1. 找到 TARGETS > Runner GeneralDeployment 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 {
  }

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

添加 注册环信Id 代码

Demo 中使用 sdk 注册环信id,在真实环境中,可以由你的后台调用环信rest api,

_signUp 方法中添加登录代码。

void _signUp() async {
  if (_username.isEmpty || _password.isEmpty) {
    _addLogToConsole("username or password is null");
    return;
  }

  try {
    _addLogToConsole("begin create account...");
    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}");
  }
}

添加登录

_signIn 方法中添加登录代码。

void _signIn() async {
  if (_userId.isEmpty || _password.isEmpty) {
    _addLogToConsole("username or password is null");
    return;
  }

  try {
    await EMClient.getInstance.login(_userId, _password);
    _addLogToConsole("sign in succeed, username: $_userId");
  } 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.addEventHandler(
    // EMChatEventHandle 对应的 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 方法中添加代码移除监听:

@override
void dispose() {
  EMClient.getInstance.chatManager.removeMessageEvent("UNIQUE_HANDLER_ID");
  EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
  super.dispose();
}

运行项目

以 iOS 为例,首先打开模拟器,之后在终端输入。

flutter run

More Repositories

1

emchat-server-examples

PHP
523
star
2

web-im

环信 web im sdk
JavaScript
353
star
3

sdkdemoapp3.0_android

Java
312
star
4

easeui

Java
290
star
5

webim-weixin-xcx

JavaScript
198
star
6

webim-react-native

JavaScript
193
star
7

sdkdemoapp3.0_ios

Objective-C
144
star
8

easemob-demo-react

JavaScript
125
star
9

webim-vue-demo

Easemob webim demo built on top of vue from scratch.
JavaScript
109
star
10

kefu-android-demo

demo app for help desk cloud
Java
94
star
11

sdk-ios-cocoapods

环信iOS SDK CocoaPod repo
Objective-C
78
star
12

webim-uniapp-demo

Vue
75
star
13

chat-android

Java
74
star
14

easeui_ios

Objective-C
74
star
15

livestream_demo_android

Java
68
star
16

kefu-ios-demo

demo app for easemob help desk cloud
Objective-C
53
star
17

livestream_demo_ios

直播demo iOS
Objective-C
49
star
18

kefu-webim

JavaScript
40
star
19

easeui-ios-hyphenate-cocoapods

cocoapods for Hyphenate EaseUI
Objective-C
35
star
20

SwallowKeeper

The description of the repo.
Python
34
star
21

easemob-demo-ios

Objective-C
21
star
22

videocall-android

Java
18
star
23

sdk-ios-cocoapods-integration

Objective-C
18
star
24

easemob-im-server-sdk

IM server SDK
Java
18
star
25

sdkdemoapp_windows

Windows demo
JavaScript
15
star
26

Circle-Demo-Web

JavaScript
13
star
27

www.easemob.com

环信
HTML
12
star
28

easemob-demo-appserver

IM app-server.
Java
10
star
29

easemob_supercommunity

Java
10
star
30

easecallkitui-android

Java
9
star
31

easemob-uikit-react

TypeScript
9
star
32

mua

Java
8
star
33

liveroom-android

Java
7
star
34

medical_treatment_demo

Vue
6
star
35

EasemobVoice

Java
6
star
36

easeui-ios-cocoapods

Objective-C
5
star
37

ease_call_kit

Easemob Callkit
Dart
5
star
38

emclient-unity

C#
5
star
39

Easemob2023-Innovation-Challenge

JavaScript
5
star
40

easemob-uikit-ios

Swift
5
star
41

whiteboard_demo_web

JavaScript
4
star
42

kefu-agent-android

The description of the repo.
Java
4
star
43

easemob-push-server-sdk

Java
4
star
44

learn-easemob

JavaScript
4
star
45

flutter_chat_uikit

Dart
4
star
46

videocall-web

JavaScript
4
star
47

EasemobCircle-2022-Innovation-Challenge

JavaScript
4
star
48

easemob-doc

Shell
3
star
49

easecallkitui-ios

Objective-C
3
star
50

Creative-Challenge-MQTT

MQTT challenge
3
star
51

kefu-agent-ios

The description of the repo.
Objective-C
3
star
52

voiceroom_demo_android

Java
2
star
53

liveroom-ios

Objective-C
2
star
54

UIKit_Chatroom_ios

Swift
2
star
55

easemob-007-token

Java
2
star
56

easemob-support

Vue
2
star
57

UIKit_Chatroom_android

Kotlin
2
star
58

easemob-uikit-flutter

Dart
2
star
59

react-native-chat-sdk

TypeScript
2
star
60

voiceroom_demo_ios

Swift
1
star
61

im-php-server-sdk

PHP Server SDK for IM.
PHP
1
star
62

easemob-demo-android

Kotlin
1
star
63

easemob_flutter_chat

Flutter chat demo.
Dart
1
star
64

emclient-u3d

u3d sdk for Easemob IM
Objective-C
1
star
65

kefu-scripts

2023年4月4日已迁移至gitlab上
Shell
1
star
66

easemob-voiceroom

Java
1
star
67

livestream-demo-app-server

Java
1
star
68

docs

官网上的文档网站
PHP
1
star
69

Circle-Demo-Android

Java
1
star
70

kefu-vec-webim

JavaScript
1
star
71

whiteboard_demo_android

Java
1
star
72

videocall-ios

Objective-C
1
star
73

UIKit_Chatroom_flutter

Dart
1
star
74

UIKit_Chatroom_rn

TypeScript
1
star
75

easemob-uikit-reactnative

TypeScript
1
star
76

Demo-ChattyAI

Java
1
star
77

flutter_chat_callkit

Dart
1
star
78

easemob-uikit-android

Kotlin
1
star