Skip to content

flutter tcp sdk and demo #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions demo_src/TCP_Client/MobileIMSDK4fDemo_tcp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
201 changes: 201 additions & 0 deletions demo_src/TCP_Client/MobileIMSDK4fDemo_tcp/lib/chat_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import 'dart:async';

import 'package:get/get.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/client_core_sdk.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/conf/config_entity.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/core/auto_relogin_daemon.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/core/keep_alive_daemon.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/core/local_data_sender.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/core/qos_4_receive_daemon.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/core/qos_4_send_daemon.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/event/chat_base_event.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/event/chat_message_event.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/event/message_qoS_event.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/utils/Ext.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/utils/log.dart';
import 'package:mobile_im_sdk_flutter_tcp/server/protocol/c/p_login_info.dart';
import 'package:mobile_im_sdk_flutter_tcp/server/protocol/protocol.dart';
import 'package:mobile_im_sdk_flutter_tcp/server/protocol/s/p_kickout_info.dart';
import 'package:oktoast/oktoast.dart';

import 'test_home_page.dart';

class ChatBaseEventImpl extends ChatBaseEvent {
final _tag = "登录";

late ChatController _chat;

void setChatController(ChatController chatController) {
_chat = chatController;
}

void _refreshState() {
_chat.refreshState();
}


@override
void onLinkClose(int errorCode) {
_refreshState();
final info =
"[error] $_tag ${nowHmsStrWithMark()} 与服务端的通信断开的回调事件通知:$errorCode";
Log.error(info, _tag);
_chat.msgList.add(info);
}

@override
void onLoginResponse(int errorCode) {
_refreshState();
final info = "$_tag ${nowHmsStrWithMark()} 结果:$errorCode";
Log.info(info, _tag);
_chat.msgList.add(info);
ClientCoreSDK.getInstance().setLoginHasInit(errorCode == 0);
if (errorCode == 0) {
Get.to(const TestHomePage());
} else {
showToast("登录失败:$errorCode");
}
}

@override
void onKickOut(PKickoutInfo kickOutInfo) {
_refreshState();
final info = "[error] $_tag ${nowHmsStrWithMark()} 被踢:$kickOutInfo";
Log.error(info, _tag);
_chat.msgList.add(info);
}

}

class ChatMessageEventImpl extends ChatMessageEvent {
final _tag = "消息";

late ChatController _chat;

void setChatController(ChatController chatController) {
_chat = chatController;
}

void _refreshMsg() {}

@override
void onErrorResponse(int errorCode, String errorMsg) {
final info =
"$_tag ${nowHmsStrWithMark()} 【DEBUG_UI】收到服务端错误消息,errorCode=$errorCode errorMsg:$errorMsg";
Log.warn(info, _tag);
_chat.msgList.add(info);
}

@override
void onReceiveMessage(String fingerPrintOfProtocol, String userid,
String dataContent, int typeu) {
final info =
"$_tag ${nowHmsStrWithMark()} 【DEBUG_UI】[typeu=$typeu]收到来自用户 $userid 的消息: $dataContent";
Log.info(info, _tag);
_chat.msgList.add(info);
_chat.newestReceiveMsg.value = info;
}
}

class MessageQoSEventImpl extends MessageQoSEvent {
final _tag = "消息QoS";

late ChatController _chat;

void setChatController(ChatController chatController) {
_chat = chatController;
}

void _refreshState() {}

@override
void messagesBeReceived(String theFingerPrint) {
final info =
"$_tag ${nowHmsStrWithMark()} 【DEBUG_UI】收到对方已收到消息事件的通知,fp=$theFingerPrint";
Log.info(info, _tag);
_chat.msgList.add(info);
}

@override
void messagesLost(List<Protocol> lostMessages) {
final info =
"$_tag ${nowHmsStrWithMark()} 【DEBUG_UI】收到系统的未实时送达事件通知,当前共有 ${lostMessages.length} 个包QoS保证机制结束,判定为【无法实时送达】!";
Log.warn(info, _tag);
_chat.msgList.add(info);
}
}

class ChatController extends GetxController {
final sdk = ClientCoreSDK.getInstance();

final linkState = false.obs;

/// 重连
final reLinkState = false.obs;

/// 心跳
final heartbeatState = false.obs;

/// 送达(发)
final qosSendState = false.obs;

/// 送达(收)
final qosReceiveState = false.obs;

final msgList = RxList();

final newestReceiveMsg = "".obs;

Timer? _periodicSecTimer;

@override
void onInit() {
super.onInit();
_initSdk();
_periodicSecTimer = Timer.periodic(const Duration(seconds: 3), (timer) {
refreshState();
});
}

@override
void dispose() {
super.dispose();
_periodicSecTimer?.cancel();
sdk.release();
}

void _initSdk() {
msgList.clear();
sdk
..init()
..setChatBaseEvent(ChatBaseEventImpl()..setChatController(this))
..setChatMessageEvent(ChatMessageEventImpl()..setChatController(this))
..setMessageQoSEvent(MessageQoSEventImpl()..setChatController(this));
}

void refreshState() {
linkState.value = sdk.isConnectedToServer();
reLinkState.value = AutoReLoginDaemon.getInstance().isAutoReLoginRunning();
heartbeatState.value = KeepAliveDaemon.getInstance().isKeepAliveRunning();
qosSendState.value = QoS4SendDaemon.getInstance().isRunning();
qosReceiveState.value = QoS4ReceiveDaemon.getInstance().isRunning();
}

void doLogin(String ip, int port, String name, String pwd) {
_initSdk();

ConfigEntity.serverIP = ip;
ConfigEntity.serverPort = port;

LocalDataSender.getInstance().sendLogin(PLoginInfo(name, loginToken: pwd));
}

void logout() {
var i = LocalDataSender.getInstance().sendLogout();
if (i == 0) {
showToast("退出登录成功");
sdk.release();
}
refreshState();
}
}
92 changes: 92 additions & 0 deletions demo_src/TCP_Client/MobileIMSDK4fDemo_tcp/lib/loading_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

/// 有加载动画的按钮
class LoadingButton extends StatefulWidget {
final bool loading;
final String title;
final String loadingText;
final TextStyle? titleStyle;
final Widget? indicator;
final Color? loadingColor;
final Color? color;
final double radius;
final double width;
final double height;
final VoidCallback? onTap;

const LoadingButton({
super.key,
this.loading = false,
required this.title,
this.loadingText = '加载中',
this.titleStyle,
this.loadingColor,
this.color,
this.radius = 0,
this.height = 30,
this.width = 100,
this.indicator,
this.onTap,
});

@override
State<LoadingButton> createState() => _LoadingButtonState();
}

class _LoadingButtonState extends State<LoadingButton> {
@override
void initState() {
super.initState();
}

/// 标题
Text _titleWidget() => Text(
widget.loading ? widget.loadingText : widget.title,
style: widget.titleStyle ??
const TextStyle(
fontSize: 16,
color: Colors.white,
),
overflow: TextOverflow.ellipsis,
);

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (!widget.loading && widget.onTap != null) {
widget.onTap!();
}
},
child: Container(
decoration: BoxDecoration(
color: widget.color ?? Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(widget.radius)),
),
child: TextButton(
onPressed: () {
if (!widget.loading && widget.onTap != null) {
widget.onTap!();
}
},
child: widget.loading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
widget.indicator ??
CupertinoActivityIndicator(
animating: widget.loading,
color: widget.loadingColor ?? Colors.white,
),
const SizedBox(width: 8),
_titleWidget(),
],
)
: _titleWidget(),
),
),
);
}
}
43 changes: 43 additions & 0 deletions demo_src/TCP_Client/MobileIMSDK4fDemo_tcp/lib/log.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:mobile_im_sdk_flutter_tcp/sdk/utils/ext.dart';

class Log {
static Function? cacheLogInfo;

static final Logger _logger = Logger(
printer: PrefixPrinter(PrettyPrinter()),
);

static void i(dynamic message, String? tag) {
if (kDebugMode) {
var info = "$tag ${nowHmsStrWithMark()}--> $message";
print(info);
cacheLogInfo?.call(info);
}
}

static void d(dynamic message, String? tag) {
if (kDebugMode) {
_logger.d("$tag --> $message", time: DateTime.now());
}
}

static void w(dynamic message, String? tag) {
if (kDebugMode) {
_logger.w("$tag --> $message", time: DateTime.now());
}
}

static void e(dynamic message, String? tag) {
if (kDebugMode) {
_logger.e("$tag --> $message", time: DateTime.now());
}
}

static void f(dynamic message, String? tag) {
if (kDebugMode) {
_logger.f("$tag --> $message", time: DateTime.now());
}
}
}
Loading