Flutter即时通讯插件nim_core的使用
Flutter即时通讯插件nim_core的使用
NIM Plugin for Flutter
NIM Plugin for Flutter是网易云信提供的一个Flutter插件,旨在帮助开发者快速集成即时通讯功能。通过这个插件,您可以在您的Flutter应用中轻松实现聊天、消息推送等功能。
要了解更多关于NIM
的信息,请访问官网。
Getting Started
开始使用NIM
for Flutter之前,请参考官方文档以获取详细的配置和初始化指南。
Usage
以下是使用nim_core
插件的一个完整示例demo,该示例展示了如何初始化SDK、登录、发送消息以及处理各种事件监听等基本操作。
示例代码
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:universal_io/io.dart';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:nim_core/nim_core.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// For Publish Use
static const appKey = 'Your_App_Key';
static const account = 'Account_ID';
static const token = 'Account_Token';
static const friendAccount = 'Friend_Account_ID';
static const chatroomId = '123456789';
final subscriptions = <StreamSubscription>[];
Uint8List? _deviceToken;
void updateAPNsToken() {
if (NimCore.instance.isInitialized && Platform.isIOS && _deviceToken != null) {
NimCore.instance.settingsService.updateAPNSToken(_deviceToken!, null);
}
}
@override
void initState() {
super.initState();
if (!kIsWeb) {
MethodChannel('com.netease.NIM.demo/settings')
.setMethodCallHandler((call) async {
if (call.method == 'updateAPNsToken') {
print('update APNs token');
_deviceToken = call.arguments as Uint8List;
}
return null;
});
}
subscriptions.add(NimCore.instance.authService.authStatus.listen((event) {
print('AuthService##auth status event : ${event.status.name}');
}));
subscriptions.add(NimCore.instance.messageService.onMessage.listen((messages) {
messages.forEach((message) {
print(
'MessageService##receive message: ${message.fromNickname} says ${message.content}');
});
}));
// 其他事件监听...
_doInitializeSDK();
}
void _doInitializeSDK() async {
late NIMSDKOptions options;
if (Platform.isAndroid) {
final directory = await getExternalStorageDirectory();
options = NIMAndroidSDKOptions(
appKey: appKey,
shouldSyncStickTopSessionInfos: true,
sdkRootDir:
directory != null ? '${directory.path}/NIMFlutter' : null);
} else if (Platform.isIOS) {
final directory = await getApplicationDocumentsDirectory();
options = NIMIOSSDKOptions(
appKey: appKey,
shouldSyncStickTopSessionInfos: true,
sdkRootDir: '${directory.path}/NIMFlutter',
apnsCername: 'ENTERPRISE',
pkCername: 'DEMO_PUSH_KIT',
);
} else if (kIsWeb) {
options = NIMIOSSDKOptions(
appKey: appKey,
shouldSyncStickTopSessionInfos: true,
sdkRootDir: null,
apnsCername: 'ENTERPRISE',
pkCername: 'DEMO_PUSH_KIT',
);
}
NimCore.instance.initialize(options).then((value) async {
NimCore.instance.authService.dynamicTokenProvider = (account) async {
print('AuthService##getDynamicToken: $account');
final currentTime = DateTime.now().millisecondsSinceEpoch;
final ttl = 600;
final secret = '';
final signature =
sha1.convert(utf8.encode('$appKey$account$currentTime$ttl$secret'));
return base64.encode(utf8.encode(
'{"signature":"$signature","curTime":$currentTime,"ttl":$ttl}'));
};
final loginResult = await NimCore.instance.authService.login(NIMLoginInfo(
account: account,
token: token,
//authType: NIMAuthType.authTypeDynamic,
));
print('login result: $loginResult');
updateAPNsToken();
// 发送文本消息示例
var textMessage1 = await MessageBuilder.createTextMessage(
sessionId: friendAccount,
sessionType: NIMSessionType.p2p,
text: '快捷评论消息',
);
await NimCore.instance.messageService.sendMessageReceipt(
message: textMessage1.data!, sessionId: '1212121');
NIMAntiSpamOption anTiOption = NIMAntiSpamOption(content: "{}");
textMessage1.data?.antiSpamOption = anTiOption;
textMessage1 = await NimCore.instance.messageService
.sendMessage(message: textMessage1.data!);
// 发送图片消息示例
final imagePath = Platform.isAndroid
? (await getExternalStorageDirectory())!.path + "/test.jpg"
: (await getApplicationDocumentsDirectory()).path + "/test.jpg";
MessageBuilder.createImageMessage(
sessionId: friendAccount,
sessionType: NIMSessionType.p2p,
filePath: imagePath,
fileSize: 0,
displayName: 'image',
).then<NIMResult>((result) {
if (result.isSuccess) {
result.data!.config = NIMCustomMessageConfig(enablePush: true);
return NimCore.instance.messageService
.sendMessage(message: result.data!);
} else {
return result;
}
}).then((result) {
print(
'MessageService##send message: ${result.code} ${result.errorDetails}');
});
// 聊天室相关操作
if (!kIsWeb) {
setupChatroom();
}
// 快捷评论相关操作
var textMessage = await MessageBuilder.createTextMessage(
sessionId: friendAccount,
sessionType: NIMSessionType.p2p,
text: '快捷评论消息',
);
textMessage = await NimCore.instance.messageService
.sendMessage(message: textMessage.data!);
var result = await NimCore.instance.messageService.addQuickComment(
textMessage.data!,
1,
'ext',
true,
true,
'pushTitle',
'pushContent',
{'key': 'value'});
print('add quick comment result: ${result.toMap()}');
// 查询快捷评论
var result2 = await NimCore.instance.messageService
.queryQuickComment([textMessage.data!]);
print('query quick comment result: ${result2.toMap()}');
// 删除快捷评论
var result3 = await NimCore.instance.messageService
.removeQuickComment(
textMessage.data!,
1,
'ext',
true,
true,
'pushTitle',
'pushContent',
{'key': 'value'});
print('remove quick comment result: ${result3.toMap()}');
// 会话管理相关操作
var mySessionResult = await NimCore.instance.messageService
.queryMySession(friendAccount, NIMSessionType.p2p);
print('queryMySession result: ${mySessionResult.toMap()}');
var updateMySessionResult = await NimCore.instance.messageService
.updateMySession(friendAccount, NIMSessionType.p2p, 'new ext');
print('updateMySession result: ${updateMySessionResult.toMap()}');
var mySessionResult2 = await NimCore.instance.messageService
.queryMySession(friendAccount, NIMSessionType.p2p);
print('queryMySession2 result: ${mySessionResult2.toMap()}');
var mySessionListResult = await NimCore.instance.messageService
.queryMySessionList(0, 0, 1, 100, 1);
print('queryMySessionList result: ${mySessionListResult.toMap()}');
var deleteMySessionResult = await NimCore.instance.messageService
.deleteMySession([
NIMMySessionKey(
sessionId: friendAccount, sessionType: NIMSessionType.p2p)
]);
print('deleteMySession result: ${deleteMySessionResult.toMap()}');
var mySessionResult3 = await NimCore.instance.messageService
.queryMySession(friendAccount, NIMSessionType.p2p);
print('queryMySession3 result: ${mySessionResult3.toMap()}');
NimCore.instance.messageService
.querySessionList()
.then((value) => print("session call back"));
});
}
@override
void dispose() {
subscriptions.forEach((subscription) {
subscription.cancel();
});
super.dispose();
}
void sendSignalingInvite() {
NimCore.instance.avSignallingService
.createChannel(type: ChannelType.video)
.then((channel) {
print('AVSignallingService##createChannel result = ${channel.code}');
if (channel.isSuccess) {
NimCore.instance.avSignallingService
.joinChannel(
channelId: channel.data!.channelId, offlineEnabled: true)
.then((join) {
print('AVSignallingService##joinChannel result = ${join.code}');
if (join.isSuccess) {
var param = InviteParam(
channelId: channel.data!.channelId,
accountId: friendAccount,
requestId: '6');
NimCore.instance.avSignallingService.invite(param).then((invite) {
print('AVSignallingService##invite result = ${invite.code}');
});
}
});
}
});
}
void loginQChat() async {
var result = await NimCore.instance.qChatService.login(QChatLoginParam());
print("login qchat result => $result.");
}
void testForQChatServer() async {
var antiSpamConfig = QChatAntiSpamConfig()..antiSpamBusinessId = '100';
var param = QChatCreateServerParam("fluterQChatServer1")
..applyJoinMode = QChatApplyJoinMode.agreeNeed
..inviteMode = QChatInviteMode.agreeNeedNot
..custom = 'custom'
..searchEnable = true
..searchType = 1
..antiSpamConfig = antiSpamConfig
..icon = '';
var result = await NimCore.instance.qChatServerService.createServer(param);
print("createServer qchat result => $result.");
}
void logoutQChat() async {
var result = await NimCore.instance.qChatService.logout();
print("logout qchat result => $result.");
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(),
),
);
}
void setupChatroom() {
var chatroomService = NimCore.instance.chatroomService;
chatroomService.onEventNotified.listen((event) {
print('ChatroomService##on event notified: $event');
});
chatroomService.onMessageStatusChanged.listen((event) {
print(
'ChatroomService##on message status changed: ${event.uuid} ${event.status}');
});
chatroomService.onMessageAttachmentProgressUpdate.listen((event) {
print(
'ChatroomService##on message attachment progress update: ${event.id} ${event.progress}');
});
chatroomService.onMessageReceived.listen((messages) {
messages.forEach((message) {
print(
'ChatroomService##on message received: ${message.fromAccount} ${message.fromNickname} '
'\'${message.content}\' ${message.extension?.nickname} ${message.extension?.senderExtension}');
final attachment = message.messageAttachment;
if (attachment is NIMChatroomNotificationAttachment) {
print('ChatroomService##on notification: ${attachment.operatorNick} '
'${NIMChatroomNotificationTypes.typeToString(attachment.type)}');
}
if (message.content == 'fetch room info') {
chatroomService.fetchChatroomInfo(chatroomId).then((value) {
print(
'ChatroomService##fetch updated chatroom info: ${value.data?.name} '
'${value.data?.announcement}');
});
}
final setAnnouncement = RegExp(r'^set announcement (.+)$')
.firstMatch(message.content ?? '');
if (setAnnouncement != null) {
chatroomService
.updateChatroomInfo(
roomId: chatroomId,
request: NIMChatroomUpdateRequest(
announcement: setAnnouncement.group(1),
),
needNotify: true,
)
.then((value) {
print(
'ChatroomService##set chatroom announcement: ${value.code} ${value.errorDetails}');
});
}
final pollMessage = RegExp(r'^poll message( [0-9]*)$')
.firstMatch(message.content ?? '');
if (pollMessage != null) {
chatroomService.fetchMessageHistory(
roomId: chatroomId,
startTime: DateTime.now().millisecondsSinceEpoch,
limit:
max(1, int.tryParse(pollMessage.group(1)?.trim() ?? '1') ?? 1),
direction: QueryDirection.QUERY_OLD,
messageTypeList: [NIMMessageType.text],
).then((messages) {
var index = 0;
messages.data?.forEach((message) {
print(
'ChatroomService##message history: ${index++} ${message.fromAccount} ${message.fromNickname} '
'\'${message.content}\'');
});
});
}
if (message.content == 'poll queue') {
chatroomService.fetchChatroomQueue(chatroomId).then((value) {
print(
'ChatroomService##poll queue: ${value.code} ${value.errorDetails} '
'${value.data?.map((e) => '${e.key}:${e.value}').toList()}');
});
}
if (message.content == 'clear queue') {
chatroomService.clearChatroomQueue(message.sessionId!).then((value) {
print(
'ChatroomService##clear queue: ${value.code} ${value.errorDetails}');
});
}
final pollQueueEntry = RegExp(r'^poll queue entry (.+)$')
.firstMatch(message.content ?? '');
if (pollQueueEntry != null) {
chatroomService
.pollChatroomQueueEntry(chatroomId, pollQueueEntry.group(1))
.then((value) {
print(
'ChatroomService##poll queue entry: ${value.code} ${value.errorDetails} ${value.data?.key} ${value.data?.value}');
});
}
final addQueueEntry = RegExp(r'^add queue entry (.+) (.+)$')
.firstMatch(message.content ?? '');
if (addQueueEntry != null) {
chatroomService
.updateChatroomQueueEntry(
roomId: chatroomId,
entry: NIMChatroomQueueEntry(
key: addQueueEntry.group(1) as String,
value: addQueueEntry.group(2) as String,
),
isTransient: true,
)
.then((value) {
print(
'ChatroomService##add queue entry: ${value.code} ${value.errorDetails}');
});
}
final setNickname =
RegExp(r'^set nickname (.+)$').firstMatch(message.content ?? '');
if (setNickname != null) {
chatroomService
.updateChatroomMyMemberInfo(
roomId: chatroomId,
request: NIMChatroomUpdateMyMemberInfoRequest(
nickname: setNickname.group(1) as String,
needSave: true,
),
)
.then((value) {
print(
'ChatroomService##update chatroom my info: ${value.code} ${value.errorDetails}');
});
}
if (message.content == 'ping') {
ChatroomMessageBuilder.createChatroomTextMessage(
roomId: message.sessionId!,
text: 'pong',
).then<NIMResult>((result) {
if (result.isSuccess) {
return chatroomService.sendChatroomMessage(result.data!);
} else {
return result;
}
}).then((value) {
print(
'ChatroomService##send message: ${value.code} ${value.errorDetails}');
});
}
final fetchMembers = RegExp(r'^fetch members( [0-9]*)$')
.firstMatch(message.content ?? '');
if (fetchMembers != null) {
chatroomService
.fetchChatroomMembers(
roomId: chatroomId,
queryType: NIMChatroomMemberQueryType.values.firstWhere(
(element) =>
element.index ==
int.tryParse(fetchMembers.group(1)?.trim() ?? '0'),
orElse: () => NIMChatroomMemberQueryType.allNormalMember),
limit: 10,
)
.then((result) {
var index = 0;
result.data?.forEach((member) {
print(
'ChatroomService fetchChatroomMembers ##member_${index++}: ${member.account} ${member.nickname} ${member.memberType}');
});
});
}
final fetchMember =
RegExp(r'^fetch member (.+)$').firstMatch(message.content ?? '');
if (fetchMember != null) {
chatroomService.fetchChatroomMembersByAccount(
roomId: chatroomId,
accountList: [fetchMember.group(1) as String]).then((result) {
final member = result.data != null && result.data!.isNotEmpty
? result.data![0]
: null;
print(
'ChatroomService fetch member: ${member?.account} ${member?.nickname} ${member?.memberType}');
});
}
if (message.content == 'mute me') {
chatroomService
.markChatroomMemberTempMuted(
duration: 5000,
options: NIMChatroomMemberOptions(
roomId: chatroomId,
account: message.fromAccount!,
),
needNotify: true,
)
.then((result) {
print(
'ChatroomService temp mute member: ${result.code} ${result.errorDetails}');
});
}
});
});
chatroomService
.enterChatroom(NIMChatroomEnterRequest(
roomId: chatroomId,
notifyExtension: {
'senderAccount': account,
'sendDate': DateTime.now().toString(),
'platform': Platform.operatingSystem,
},
extension: {
'senderAccount': account,
'sendDate': DateTime.now().toString(),
'platform': Platform.operatingSystem,
},
))
.then((value) {
print(
'ChatroomService##enter chatroom: ${value.code} ${value.errorDetails}');
ChatroomMessageBuilder.createChatroomTextMessage(
roomId: chatroomId,
text: 'Hello everybody. This is $account',
).then((value) {
chatroomService.sendChatroomMessage(value.data!).then((value) {
print('send text chatroom message');
});
});
});
}
}
Notice
请注意,Web和PC版本的组件仍在测试阶段,不建议直接集成。如果您有特殊需求,请联系我们的业务部门。
希望以上内容对您有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter即时通讯插件nim_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter即时通讯插件nim_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用即时通讯插件nim_core
的示例代码。请注意,实际使用中需要根据nim_core
的官方文档和最新版本进行适当调整。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加nim_core
的依赖:
dependencies:
flutter:
sdk: flutter
nim_core: ^最新版本号 # 请替换为实际最新版本号
然后运行flutter pub get
来安装依赖。
2. 配置Android和iOS项目
根据nim_core
的官方文档,你可能需要在AndroidManifest.xml
和Info.plist
文件中添加一些必要的配置。例如,在AndroidManifest.xml
中:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<!-- 其他配置 -->
<application
android:name=".MyApplication" <!-- 确保你的Application类继承自NimApplication -->
android:label="yourapp"
android:icon="@mipmap/ic_launcher">
<!-- 其他配置 -->
<!-- Nim SDK 需要的权限和服务 -->
<service android:name="com.netease.nim.uikit.service.NimService"
android:exported="true">
<intent-filter>
<action android:name="com.netease.nim.action.NIM_CONNECT_CHANGED" />
<action android:name="com.netease.nim.action.NIM_INCOMING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
<!-- 其他配置 -->
</manifest>
对于iOS,你可能需要在Info.plist
中添加一些必要的权限配置,具体请参考nim_core
的官方文档。
3. 初始化Nim SDK
在你的Flutter项目中,创建一个新的Dart文件,例如nim_service.dart
,用于初始化和配置Nim SDK。
import 'package:flutter/material.dart';
import 'package:nim_core/nim_core.dart';
class NimService {
static NimService? _instance;
late NimClient nimClient;
NimService._() {
initNim();
}
factory NimService() {
_instance ??= NimService._();
return _instance!;
}
Future<void> initNim() async {
// 初始化NimClient
nimClient = NimClient();
// 设置SDK选项
NimSDKOptions options = NimSDKOptions(
appKey: "你的AppKey", // 请替换为你的实际AppKey
account: "用户账号", // 请替换为你的实际用户账号
token: "用户Token", // 请替换为你的实际用户Token
apsForProduction: false, // 根据你的环境设置是否为生产环境
);
// 初始化SDK
await nimClient.init(options);
// 监听连接状态变化
nimClient.onConnectStatusChangeListener = (NimConnectStatus status, int code, String desc) {
print("Connect Status Changed: $status, Code: $code, Desc: $desc");
};
// 其他配置和初始化代码...
}
// 其他Nim SDK相关的方法...
}
4. 使用NimService
在你的主应用文件中(例如main.dart
),你可以通过获取NimService
的实例来使用Nim SDK的功能。
import 'package:flutter/material.dart';
import 'nim_service.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
NimService().initNim().then((_) {
// Nim SDK 初始化完成后可以执行的操作
print("Nim SDK initialized");
});
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Nim Core Example'),
),
body: Center(
child: Text('Check the console for Nim SDK initialization status.'),
),
),
);
}
}
注意事项
- 权限和配置:确保在Android和iOS项目中正确配置了所有必要的权限和服务。
- 错误处理:在实际应用中,需要添加更多的错误处理和日志记录,以便更好地调试和维护。
- 版本兼容性:确保
nim_core
插件的版本与你的Flutter版本兼容。
以上代码只是一个基本的示例,用于展示如何在Flutter项目中使用nim_core
插件进行即时通讯的初始化。具体功能和实现可能需要根据实际需求进行调整和扩展。