Files
tongxunruanjian/mobile-next/lib/core/controller/im_controller.dart
T
编码工程师andmultica-agent 8046ec7483 feat(mobile-next): 导入官方 openim-flutter-demo 固定基线 3.8.3-patch.3 并完成双构建
- 上游: github.com/OpenIMSDK/openim-flutter-demo tag 3.8.3-patch.3
  commit b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f
- 并行目录 mobile-next/ 原样导入(含 LICENSE),不覆盖现网 mobile/
- 锁定 Flutter 3.24.5 / Dart 3.5.4 / JDK 17 / Gradle 7.6.3 / AGP 7.3.1
- 实测 Android debug 与 release 构建均成功(见 docs/mobile-next-baseline-import.md)
- 本提交可单独回退:git revert 1db1229(重写前)

Co-authored-by: multica-agent <github@multica.ai>
2026-08-19 15:24:33 +08:00

215 lines
7.4 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
import 'package:get/get.dart';
import 'package:openim_common/openim_common.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:openim_live/openim_live.dart';
import '../im_callback.dart';
class IMController extends GetxController with IMCallback, OpenIMLive {
late Rx<UserFullInfo> userInfo;
late String atAllTag;
@override
void onClose() {
super.close();
onCloseLive();
super.onClose();
}
@override
void onInit() async {
super.onInit();
onInitLive();
WidgetsBinding.instance.addPostFrameCallback((_) => initOpenIM());
}
void initOpenIM() async {
final initialized = await OpenIM.iMManager.initSDK(
platformID: IMUtils.getPlatform(),
apiAddr: Config.imApiUrl,
wsAddr: Config.imWsUrl,
dataDir: Config.cachePath,
logLevel: Config.logLevel,
logFilePath: Config.cachePath,
listener: OnConnectListener(
onConnecting: () {
imSdkStatus(IMSdkStatus.connecting);
},
onConnectFailed: (code, error) {
imSdkStatus(IMSdkStatus.connectionFailed);
},
onConnectSuccess: () {
imSdkStatus(IMSdkStatus.connectionSucceeded);
},
onKickedOffline: kickedOffline,
onUserTokenExpired: kickedOffline,
onUserTokenInvalid: userTokenInvalid,
),
);
OpenIM.iMManager
..setUploadLogsListener(OnUploadLogsListener(onUploadProgress: uploadLogsProgress))
..userManager.setUserListener(OnUserListener(
onSelfInfoUpdated: (u) {
selfInfoUpdated(u);
userInfo.update((val) {
val?.nickname = u.nickname;
val?.faceURL = u.faceURL;
val?.remark = u.remark;
val?.ex = u.ex;
val?.globalRecvMsgOpt = u.globalRecvMsgOpt;
});
},
onUserStatusChanged: userStausChanged))
..messageManager.setAdvancedMsgListener(OnAdvancedMsgListener(
onRecvC2CReadReceipt: recvC2CMessageReadReceipt,
onRecvNewMessage: recvNewMessage,
onNewRecvMessageRevoked: recvMessageRevoked,
onRecvOfflineNewMessage: recvOfflineMessage,
onRecvOnlineOnlyMessage: (msg) {
if (msg.isCustomType) {
final data = msg.customElem!.data;
final map = jsonDecode(data!);
final customType = map['customType'];
if (customType == CustomMessageType.callingInvite ||
customType == CustomMessageType.callingAccept ||
customType == CustomMessageType.callingReject ||
customType == CustomMessageType.callingCancel ||
customType == CustomMessageType.callingHungup) {
final signaling = SignalingInfo(invitation: InvitationInfo.fromJson(map['data']));
signaling.userID = signaling.invitation?.inviterUserID;
switch (customType) {
case CustomMessageType.callingInvite:
receiveNewInvitation(signaling);
break;
case CustomMessageType.callingAccept:
inviteeAccepted(signaling);
break;
case CustomMessageType.callingReject:
inviteeRejected(signaling);
break;
case CustomMessageType.callingCancel:
invitationCancelled(signaling);
break;
case CustomMessageType.callingHungup:
beHangup(signaling);
break;
}
}
}
},
))
..messageManager.setMsgSendProgressListener(OnMsgSendProgressListener(
onProgress: progressCallback,
))
..messageManager.setCustomBusinessListener(OnCustomBusinessListener(
onRecvCustomBusinessMessage: recvCustomBusinessMessage,
))
..friendshipManager.setFriendshipListener(OnFriendshipListener(
onBlackAdded: blacklistAdded,
onBlackDeleted: blacklistDeleted,
onFriendApplicationAccepted: friendApplicationAccepted,
onFriendApplicationAdded: friendApplicationAdded,
onFriendApplicationDeleted: friendApplicationDeleted,
onFriendApplicationRejected: friendApplicationRejected,
onFriendInfoChanged: friendInfoChanged,
onFriendAdded: friendAdded,
onFriendDeleted: friendDeleted,
))
..conversationManager.setConversationListener(OnConversationListener(
onConversationChanged: conversationChanged,
onNewConversation: newConversation,
onTotalUnreadMessageCountChanged: totalUnreadMsgCountChanged,
onInputStatusChanged: inputStateChanged,
onSyncServerFailed: (reInstall) {
imSdkStatus(IMSdkStatus.syncFailed, reInstall: reInstall ?? false);
},
onSyncServerFinish: (reInstall) {
imSdkStatus(IMSdkStatus.syncEnded, reInstall: reInstall ?? false);
if (Platform.isAndroid) {
Permissions.request([Permission.systemAlertWindow]);
}
},
onSyncServerStart: (reInstall) {
imSdkStatus(IMSdkStatus.syncStart, reInstall: reInstall ?? false);
},
onSyncServerProgress: (progress) {
imSdkStatus(IMSdkStatus.syncProgress, progress: progress);
}))
..groupManager.setGroupListener(OnGroupListener(
onGroupApplicationAccepted: groupApplicationAccepted,
onGroupApplicationAdded: groupApplicationAdded,
onGroupApplicationDeleted: groupApplicationDeleted,
onGroupApplicationRejected: groupApplicationRejected,
onGroupInfoChanged: groupInfoChanged,
onGroupMemberAdded: groupMemberAdded,
onGroupMemberDeleted: groupMemberDeleted,
onGroupMemberInfoChanged: groupMemberInfoChanged,
onJoinedGroupAdded: joinedGroupAdded,
onJoinedGroupDeleted: joinedGroupDeleted,
));
initializedSubject.sink.add(initialized);
}
Future login(String userID, String token) async {
try {
var user = await OpenIM.iMManager.login(
userID: userID,
token: token,
defaultValue: () async => UserInfo(userID: userID),
);
ApiService().setToken(token);
userInfo = UserFullInfo.fromJson(user.toJson()).obs;
_queryMyFullInfo();
_queryAtAllTag();
} catch (e, s) {
Logger.print('e: $e s:$s');
await _handleLoginRepeatError(e);
return Future.error(e, s);
}
}
Future logout() {
return OpenIM.iMManager.logout();
}
void _queryAtAllTag() async {
atAllTag = OpenIM.iMManager.conversationManager.atAllTag;
}
void _queryMyFullInfo() async {
final data = await Apis.queryMyFullInfo();
if (data is UserFullInfo) {
userInfo.update((val) {
val?.allowAddFriend = data.allowAddFriend;
val?.allowBeep = data.allowBeep;
val?.allowVibration = data.allowVibration;
val?.nickname = data.nickname;
val?.faceURL = data.faceURL;
val?.phoneNumber = data.phoneNumber;
val?.email = data.email;
val?.birth = data.birth;
val?.gender = data.gender;
});
}
}
_handleLoginRepeatError(e) async {
if (e is PlatformException && (e.code == "13002" || e.code == '1507')) {
await logout();
await DataSp.removeLoginCertificate();
}
}
}