flutter 调用环信sdk 实现即时通讯
首先下载依赖
导包
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
登录
import 'package:flutter/material.dart';
import 'package:test1/Do/UserDao.dart'; // Make sure this path is correct
import 'package:test1/page/logined.dart';
import 'register.dart'; // Import your RegisterPage class
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
class LoginPage extends StatefulWidget {
LoginPage({required Key key}) : super(key: key);
@override
_LoginPage createState() => _LoginPage();
}
class _LoginPage extends State<LoginPage> {
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: const Text('登录'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
decoration: const InputDecoration(hintText: "输入用户名"),
onChanged: (username) => _username = username,
),
const SizedBox(height: 20.0),
TextField(
decoration: const InputDecoration(hintText: "输入密码"),
onChanged: (password) => _password = password,
),
const SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
// Remove extra condition check
if (_username.isNotEmpty && _password.isNotEmpty) {
// 调用后端登录函数
login(context, _username, _password);
// Navigate to MyApp2 with username parameter
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyApp2(username: _username),
),
);
} else {
// 提示用户输入完整的信息
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请输入完整的信息'),
),
);
}
_signIn();
},
child: const Text('登录'),
),
const SizedBox(height: 10.0),
TextButton(
onPressed: () {
// Navigate to the RegisterPage
Navigator.push(
context,
MaterialPageRoute(builder: (context) => RegisterPage(key: UniqueKey())),
);
},
child: const Text('注册'),
),
],
),
),
);
}
void _initSDK() async {
EMOptions options = EMOptions(
appKey: "1169240414209351#youxiandechulun",
autoLogin: false,
);
await EMClient.getInstance.init(options);
// 通知sdk ui已经准备好,执行后才会收到`EMChatRoomEventHandler`, `EMContactEventHandler`, `EMGroupEventHandler` 回调。
await EMClient.getInstance.startCallback();
}
void _addChatListener() {
// 添加消息状态变更监听
EMClient.getInstance.chatManager.addMessageEvent(
// ChatMessageEvent 对应的 key。
"UNIQUE_HANDLER_ID",
ChatMessageEvent(
onSuccess: (msgId, msg) {
_addLogToConsole("发送消息成功");
},
onProgress: (msgId, progress) {
_addLogToConsole("发送消息成功");
},
onError: (msgId, msg, error) {
_addLogToConsole(
"发送消息失败,代码: ${error.code}, 描述: ${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(
"接收到文本消息: ${body.content}, 来自: ${msg.from}",
);
}
break;
case MessageType.IMAGE:
{
_addLogToConsole(
"接收到图片消息, 来自: ${msg.from}",
);
}
break;
case MessageType.VIDEO:
{
_addLogToConsole(
"接收到视频消息, 来自: ${msg.from}",
);
}
break;
case MessageType.LOCATION:
{
_addLogToConsole(
"接收到位置消息, 来自: ${msg.from}",
);
}
break;
case MessageType.VOICE:
{
_addLogToConsole(
"接收到语音消息, 来自: ${msg.from}",
);
}
break;
case MessageType.FILE:
{
_addLogToConsole(
"接收到文件消息, 来自: ${msg.from}",
);
}
break;
case MessageType.CUSTOM:
{
_addLogToConsole(
"接收到自定义消息, 来自: ${msg.from}",
);
}
break;
case MessageType.CMD:
{
// 当前回调中不会有 CMD 类型消息,CMD 类型消息通过 [EMChatEventHandler.onCmdMessagesReceived] 回调接收
}
break;
case MessageType.COMBINE:
// TODO: Handle this case.
}
}
},
),
);
}
void _signIn() async {
if (_username.isEmpty || _password.isEmpty) {
_addLogToConsole("用户名或密码为空");
return;
}
try {
await EMClient.getInstance.login(_username, _password);
_addLogToConsole("登录成功, 用户名: $_username");
} on EMError catch (e) {
_addLogToConsole("登录失败, 错误代码: ${e.code} , ${e.description}");
}
}
void _signOut() async {
try {
await EMClient.getInstance.logout(true);
_addLogToConsole("退出成功");
} on EMError catch (e) {
_addLogToConsole(
"退出失败, 代码: ${e.code}, 描述: ${e.description}");
}
}
void _signUp() async {
if (_username.isEmpty || _password.isEmpty) {
_addLogToConsole("用户名或密码为空");
return;
}
try {
_addLogToConsole("开始创建账号...");
await EMClient.getInstance.createAccount(_username, _password);
_addLogToConsole("创建账号成功, 用户名: $_username");
} on EMError catch (e) {
_addLogToConsole(
"创建账号失败, 代码: ${e.code}, 描述: ${e.description}");
}
}
void _sendMessage() async {
if (_chatId.isEmpty || _messageContent.isEmpty) {
_addLogToConsole("聊天ID或消息内容为空");
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;
}
}
注册
import 'package:flutter/material.dart';
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
import '../Do/UserDao.dart';
class RegisterPage extends StatefulWidget {
const RegisterPage({Key? key}) : super(key: key);
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
TextEditingController _usernameController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
TextEditingController _usernameController2 = TextEditingController();
TextEditingController _phoneNumberController = TextEditingController();
TextEditingController _emailController = TextEditingController();
@override
void initState() {
super.initState();
_initSDK();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('注册')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: _usernameController,
decoration: const InputDecoration(labelText: '账号'),
),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: '密码'),
obscureText: true,
),
TextFormField(
controller: _usernameController2,
decoration: const InputDecoration(labelText: '用户名'),
obscureText: true,
),
TextFormField(
controller: _phoneNumberController,
decoration: const InputDecoration(labelText: '手机号'),
keyboardType: TextInputType.phone,
),
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: '邮箱'),
keyboardType: TextInputType.emailAddress,
),
SizedBox(height: 16),
ElevatedButton(
onPressed:(){
String username = _usernameController.text.trim();
String password = _passwordController.text.trim();
String username2 = _usernameController2.text.trim();
String phoneNumber = _phoneNumberController.text.trim();
String email = _emailController.text.trim();
// 做简单的输入验证,你也可以根据需要增加更多的验证逻辑
if (username.isNotEmpty &&
password.isNotEmpty &&
username2.isNotEmpty &&
phoneNumber.isNotEmpty &&
email.isNotEmpty) {
// 调用后端注册函数
register(context, username, password, username2, phoneNumber, email);
} else {
// 提示用户输入完整的信息
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请输入完整的信息'),
),
);
}
_signUp();
},
child: const Text('注册'),
),
],
),
),
);
}
void _initSDK() async {
EMOptions options = EMOptions(
appKey: "1169240414209351#youxiandechulun",
autoLogin: false,
);
await EMClient.getInstance.init(options);
await EMClient.getInstance.startCallback();
}
Future<void> _signUp() async {
final username = _usernameController.text.trim();
final password = _passwordController.text.trim();
try {
await EMClient.getInstance.createAccount(username, password);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('注册成功')),
);
// 注册成功后可以做一些清理或导航操作
} on EMError catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('注册失败, 代码: ${e.code}, 描述: ${e.description}')),
);
}
}
}
flutter 调用环信sdk 实现即时通讯的更多相关文章
- android-使用环信SDK开发即时通信功能及源代码下载
近期项目中集成即时聊天功能.挑来拣去,终于选择环信SDK来进行开发,选择环信的主要原因是接口方便.简洁.说明文档清楚易懂.文档有android.ios.和后台server端.还是非常全的. 环信官网: ...
- 基于环信SDK的IM即时通讯填坑之路(vue)
公司最近使用第三方环信SDK的进行通信聊天,基本已完成.记录下填坑之路 1.可以通过以下方式引用 WebSDK 1.安装 npm install easemob-websdk --save 2. 先 ...
- 环信SDK集成
利用环信SDK可以实现即时通讯,但在集成的过程中碰到了不少的坑. 注意 选择项目路径,这里以最新版环信demo为例 注意:环信的ChatDemoUI这个demo里边因为研发的同事为了照顾老版本的And ...
- 李洪强iOS开发之-环信02.2_环信官网下载环信 SDK
李洪强iOS开发之-环信02.2_环信官网下载环信 SDK 移动客服即时通讯云 iOS SDK 当前版本:V3.1.4 2016-07-08 [ 版本历史 ] | 开发指南 | 知识库 | Demo源 ...
- 集成IOS 环信SDK
集成IOS SDK 在您阅读此文档时,我们假定您已经具备了基础的 iOS 应用开发经验,并能够理解相关基础概念. 下载SDK 通过Cocoapods下载地址 不包含实时语音版本SDK(EaseMobC ...
- 李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入
李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入 01 - 直接在项目中导入SDK和一些静态库 这个时候,没有错误的编译没有错误的话,就说明SDK已经配置成功 还有一种方法是用cocoap ...
- 李洪强iOS开发之-环信02.1_环信 SDK 2.x到3.0升级文档
李洪强iOS开发之-环信02.1_环信 SDK 2.x到3.0升级文档 SDK 2.x 至 3.0 升级指南 环信 SDK 3.0 升级文档 3.0 中的核心类为 EMClient 类,通过 EMCl ...
- 环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)
前言: 环信的SDK在公司的项目中有用到,现在用到的是群聊的部分,这里我们分析总结一下自己对环信给的DEMO大概的拆解一下,说说我们怎么样充分的利用这个demo来写我们所需要的业务.这个也由于篇幅的原 ...
- 环信SDK与Apple Watch的结合(2)
这一篇主要是介绍怎么拖apple watch上的相关页面,附源码EMWatchOCDemo. 需要在工程中的“EMWatchOCDemo WatchKit App”中进行操作,该文件夹的结构如图 Wa ...
- 环信SDK与Apple Watch的结合(1)
该系列是记录在apple watch上开发IM,用到了最近挺流行的环信IM SDK. 一.先来一段网上随处可查到的信息: 1.两种分辨率 1.65寸 312*390 1.5寸 272*340 2.开发 ...
随机推荐
- 我在阿里巴巴做 Serverless 云研发平台
简介: Serverless 云研发平台经过这半年多的蜕变,已经从简单的解决工程链路的平台演进成一个面向研发.上线.运维的全生命周期研发平台,后续要解决的命题会集中在用户低门槛上. 作者 | 林昱(苏 ...
- 如何专业化监控一个Kubernetes集群?
简介: 本文会介绍 Kubernetes 可观测性系统的构建,以及基于阿里云云产品实现 Kubernetes 可观测系统构建的最佳实践. 作者:佳旭 阿里云容器服务技术专家 引言 Kubernetes ...
- [Docker] 假如宿主机 Nginx 代理到 Docker 的 PHP
其实没有多少区别,同样 php 镜像启动服务暴露一个端口,nginx 的 proxy_pass 代理过去,唯一要注意的是 nginx 配置的项目路径. nginx 配置的 root 是本地项目路径,给 ...
- Roslyn 分析器 EnforceExtendedAnalyzerRules 属性的作用
在开始编写 dotnet 的 Roslyn 分析器项目时,会被 VisualStudio 通过 RS1036 要求在项目文件配置上 EnforceExtendedAnalyzerRules 属性,本文 ...
- WPF 引用 UWP 控件 不打包为 MSIX 分发的方法
按照微软的官方文档,大部分的文档都会说如果用了 XAML Islands 等技术的时候,需要新建一个打包项目,将 WPF 应用打包为 msix 等才可以进行分发和使用.但是实际上不打包也可以,此时可以 ...
- SpringBoot获取配置:@Value、@ConfigurationProperties方式
配置文件yml # phantomjs的位置地址 phantomjs: binPath: windows: binPath-win linux: binPath-linux jsPath: windo ...
- WPF-dataGrid动态更新
简介: 问题:在WPF中,使用了ObservableCollection<T>作为dataGrid的数据源,发现更新数据的时候不会触发dataGrid的更新 By MaQaQ 2023-1 ...
- arcmap利用合并工具修改字段名称、类型、顺序
- C数据结构线性表:实现顺序表的增删改查&完整篇
文章目录 ①前言 顺序表结构体的定义 ②初始化顺序表 ③插入新的元素 插入的时候需要特别注意的几点 ④删除元素 第一个删除元素功能实现 第二个删除元素功能实现 对代码下面中**i- -**的说明(第二 ...
- java学习之旅(day.01)
Markdown学习 标题 一级标题:#空格+标题名字 二级标题:##空格+标题名字 三级标题:###空格+标题名字 字体 粗体:两边都加两个** Hello,world 斜体:两边都加一个* Hel ...