Flutter即时通讯插件nim_core_v2的使用
Flutter即时通讯插件nim_core_v2的使用
简介
本插件为Flutter开发者提供了NetEase IM SDK V2的支持。
了解更多关于NIM的信息,请访问官方网站。
开始使用
要开始在Flutter项目中使用NIM插件,请参考官方文档。
使用方法
初始化SDK
首先需要初始化SDK,根据不同的平台配置相应的选项。
void _doInitializeSDK() async {
late NIMSDKOptions options;
if (!kIsWeb) {
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 (Platform.isMacOS || Platform.isWindows) {
NIMBasicOption basicOption = NIMBasicOption();
options = NIMPCSDKOptions(basicOption: basicOption, appKey: appKey);
}
NimCore.instance.initialize(options).then((value) async {
print('initialize result: $value');
});
}
登录
通过调用loginService
进行登录。这里展示了两种登录方式:普通登录和动态token登录。
普通登录
void loginNormal() async {
var options = NIMLoginOption();
NimCore.instance.loginService.loginExtensionProvider =
(String accountId) async {
print('dart loginExtensionProvider');
return "abd/$accountId";
};
final loginResult = await NimCore.instance.loginService.login(
accountEditingController.text, passwordEditingController.text, options);
print('login result: $loginResult');
}
动态token登录
void loginSync() async {
var options = NIMLoginOption();
options.authType = NIMLoginAuthType.authTypeDynamicToken;
NimCore.instance.loginService.tokenProvider = (String accountId) async {
print('login sync token : $accountId');
return 'georgeSYncToken';
};
NimCore.instance.loginService.loginExtensionProvider =
(String accountId) async {
print('dart loginExtensionProvider');
return "abd/$accountId";
};
final loginResult = await NimCore.instance.loginService.login(
accountEditingController.text, passwordEditingController.text, options);
print('login syncToken result: $loginResult');
}
更新APNs Token(仅限iOS和macOS)
在iOS和macOS上,如果设备有新的APNs Token,则需要更新到NIM SDK。
void updateAPNsToken() {
if (Platform.isIOS && _deviceToken != null) {
NimCore.instance.apnsService.updateApnsToken(_deviceToken!);
}
}
监听事件
可以监听登录失败、断开连接等事件。
[@override](/user/override)
void initState() {
super.initState();
subsriptions
.add(NimCore.instance.loginService.onConnectFailed.listen((event) {
print('LoginService##onConnectFailed: ${event.toJson()}');
setState(() {
loginListener = loginListener +
'\n LoginService##onConnectFailed: ${event.toJson()}';
});
}));
subsriptions
.add(NimCore.instance.loginService.onDisconnected.listen((event) {
print('LoginService##onDisconnected: ${event.toJson()}');
setState(() {
loginListener = loginListener +
'\n LoginService##onDisconnected: ${event.toJson()}';
});
}));
subsriptions
.add(NimCore.instance.loginService.onLoginFailed.listen((event) {
print('LoginService##onLoginFailed: ${event.toJson()}');
setState(() {
loginListener =
loginListener + '\n LoginService##onLoginFailed: ${event.toJson()}';
});
}));
}
完整示例
以下是完整的示例代码:
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.
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_v2/nim_core.dart';
import 'package:path_provider/path_provider.dart';
import 'package:universal_html/html.dart' as html;
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/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 subsriptions = <StreamSubscription>[];
Uint8List? _deviceToken;
void updateAPNsToken() {
if (Platform.isIOS && _deviceToken != null) {
NimCore.instance.apnsService.updateApnsToken(_deviceToken!);
}
}
String loginListener = "";
TextEditingController accountEditingController =
TextEditingController(text: account);
TextEditingController passwordEditingController =
TextEditingController(text: token);
TextEditingController reConnectEditingController = TextEditingController();
//动态token
String syncToken = "";
[@override](/user/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;
});
}
subsriptions
.add(NimCore.instance.loginService.onConnectFailed.listen((event) {
print('LoginService##onConnectFailed: ${event.toJson()}');
setState(() {
loginListener = loginListener +
'\n LoginService##onConnectFailed: ${event.toJson()}';
});
}));
subsriptions
.add(NimCore.instance.loginService.onDisconnected.listen((event) {
print('LoginService##onDisconnected: ${event.toJson()}');
setState(() {
loginListener = loginListener +
'\n LoginService##onDisconnected: ${event.toJson()}';
});
}));
subsriptions
.add(NimCore.instance.loginService.onLoginFailed.listen((event) {
print('LoginService##onLoginFailed: ${event.toJson()}');
setState(() {
loginListener =
loginListener + '\n LoginService##onLoginFailed: ${event.toJson()}';
});
}));
_doInitializeSDK();
}
void _doInitializeSDK() async {
late NIMSDKOptions options;
if (kIsWeb) {
var base = NIMInitializeOptions(
appkey: appKey,
apiVersion: 'v2',
debugLevel: 'debug',
);
options = NIMWebSDKOptions(
appKey: appKey,
initializeOptions: base,
);
} else 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 (Platform.isMacOS || Platform.isWindows) {
NIMBasicOption basicOption = NIMBasicOption();
options = NIMPCSDKOptions(basicOption: basicOption, appKey: appKey);
} else if (kIsWeb) {
var base = NIMInitializeOptions(
appkey: appKey,
);
options = NIMWebSDKOptions(
appKey: appKey,
initializeOptions: base,
);
}
NimCore.instance.initialize(options).then((value) async {
print('initialize result: $value');
});
}
Future<String> getTokenFromServer(String account) async {
var requestBody = {"appkey": appKey, "accid": account};
var header = <String, String>{
'content-type': 'application/x-www-form-urlencoded'
};
var url = Uri.parse(
"http://imtest.netease.im/nimserver/god/mockDynamicToken.action");
var response = await http.post(url, headers: header, body: requestBody);
if (response.statusCode == 200) {
var responseData = json.decode(response.body);
int code = responseData["code"];
if (code != 200) {
return "";
}
String token = responseData["data"];
return token;
} else {
return "";
}
}
Future<dynamic> createImgMsg() async {
html.File? imageObj;
String imageUrl =
'https://img2.baidu.com/it/u=1008561530,2313586183&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1730';
http.Response response = await http.get(Uri.parse(imageUrl));
var blob = html.Blob([response.bodyBytes], 'image/jpeg', 'native');
imageObj = html.File([blob], 'image.jpg');
return MessageCreator.createImageMessage(
'',
'name',
'',
40,
40,
imageObj: imageObj,
);
}
[@override](/user/override)
void dispose() {
subsriptions.forEach((subsription) {
subsription.cancel();
});
super.dispose();
}
void loginNormal() async {
var options = NIMLoginOption();
NimCore.instance.loginService.loginExtensionProvider =
(String accountId) async {
print('dart loginExtensionProvider');
return "abd/$accountId";
};
final loginResult = await NimCore.instance.loginService.login(
accountEditingController.text, passwordEditingController.text, options);
print('login result: $loginResult');
}
void loginSync() async {
var options = NIMLoginOption();
options.authType = NIMLoginAuthType.authTypeDynamicToken;
NimCore.instance.loginService.tokenProvider = (String accountId) async {
print('login sync token : $accountId');
return 'georgeSYncToken';
};
NimCore.instance.loginService.loginExtensionProvider =
(String accountId) async {
print('dart loginExtensionProvider');
return "abd/$accountId";
};
final loginResult = await NimCore.instance.loginService.login(
accountEditingController.text, passwordEditingController.text, options);
print('login syncToken result: $loginResult');
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: SingleChildScrollView(
child: Column(
children: [
Text('登录回调'),
Text(
loginListener,
maxLines: 6,
),
Text('账号'),
TextField(
controller: accountEditingController,
),
Text('token'),
TextField(
controller: passwordEditingController,
),
Text('动态token'),
Text(syncToken),
TextButton(
onPressed: () {
loginNormal();
},
child: Text('普通登录')),
TextButton(
onPressed: () {
loginSync();
},
child: Text('动态token登录')),
Text('重连次数'),
TextField(
controller: reConnectEditingController,
keyboardType: TextInputType.number,
),
TextButton(
onPressed: () {
NimCore.instance.loginService
.setReconnectDelayProvider((time) async {
int inputNum = int.parse(reConnectEditingController.text);
print(
"getReconnectDelay flutter result ${time + inputNum}");
return time + inputNum;
});
},
child: Text('设置重连次数')),
TextButton(
onPressed: () {
updateAPNsToken();
},
child: Text('updateApnsToken')),
],
),
),
),
);
}
}
更多关于Flutter即时通讯插件nim_core_v2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter即时通讯插件nim_core_v2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
nim_core_v2
是网易云信(Netease YunXin)为 Flutter 提供的一个即时通讯(IM)插件,它可以帮助开发者在 Flutter 应用中快速集成即时通讯功能。以下是如何使用 nim_core_v2
插件的基础步骤和示例代码。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 nim_core_v2
插件的依赖:
dependencies:
flutter:
sdk: flutter
nim_core_v2: ^版本号
请将 ^版本号
替换为当前最新的版本号。你可以通过 pub.dev 查找最新的版本。
2. 初始化 SDK
在使用 nim_core_v2
之前,你需要初始化 SDK。通常你可以在 main.dart
中进行初始化:
import 'package:nim_core_v2/nim_core_v2.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化网易云信 SDK
final nim = NimCore.instance;
await nim.init(
appKey: '你的AppKey',
apnsCername: '你的APNs证书名称', // 如果需要使用推送功能
);
runApp(MyApp());
}
3. 登录
初始化完成后,你可以使用 login
方法登录到网易云信的服务器:
void login() async {
final result = await NimCore.instance.authService.login(
account: '你的账号',
token: '你的token', // 通常从服务器获取
);
if (result.isSuccess) {
print('登录成功');
} else {
print('登录失败: ${result.error?.message}');
}
}
4. 发送消息
登录成功后,你可以使用 sendMessage
方法发送消息:
void sendTextMessage() async {
final message = MessageBuilder.textMessage(
sessionId: '对方的账号',
text: '你好,这是一条文本消息',
);
final result = await NimCore.instance.messageService.sendMessage(
message: message,
);
if (result.isSuccess) {
print('消息发送成功');
} else {
print('消息发送失败: ${result.error?.message}');
}
}
5. 接收消息
你可以通过监听 onMessage
事件来接收消息:
void listenForMessages() {
NimCore.instance.messageService.onMessage.listen((message) {
print('收到消息: ${message.content}');
});
}
6. 其他功能
nim_core_v2
还提供了丰富的功能,如群组管理、好友管理、音视频通话等。你可以根据官方文档和示例代码来使用这些功能。
7. 注销
在应用退出时,建议调用 logout
方法注销账号:
void logout() async {
final result = await NimCore.instance.authService.logout();
if (result.isSuccess) {
print('注销成功');
} else {
print('注销失败: ${result.error?.message}');
}
}
8. 注意事项
- 请确保你已经在网易云信后台创建了应用,并获取了正确的
AppKey
。 - 如果需要使用推送功能,请确保已经正确配置了 APNs 证书。
- 详细的使用方法和 API 文档可以参考 网易云信官方文档。
示例代码
以下是一个简单的 Flutter 应用示例,展示了如何初始化 SDK、登录、发送和接收消息:
import 'package:flutter/material.dart';
import 'package:nim_core_v2/nim_core_v2.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化网易云信 SDK
final nim = NimCore.instance;
await nim.init(
appKey: '你的AppKey',
apnsCername: '你的APNs证书名称',
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter IM Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: login,
child: Text('登录'),
),
ElevatedButton(
onPressed: sendTextMessage,
child: Text('发送消息'),
),
],
),
),
),
);
}
void login() async {
final result = await NimCore.instance.authService.login(
account: '你的账号',
token: '你的token',
);
if (result.isSuccess) {
print('登录成功');
listenForMessages();
} else {
print('登录失败: ${result.error?.message}');
}
}
void sendTextMessage() async {
final message = MessageBuilder.textMessage(
sessionId: '对方的账号',
text: '你好,这是一条文本消息',
);
final result = await NimCore.instance.messageService.sendMessage(
message: message,
);
if (result.isSuccess) {
print('消息发送成功');
} else {
print('消息发送失败: ${result.error?.message}');
}
}
void listenForMessages() {
NimCore.instance.messageService.onMessage.listen((message) {
print('收到消息: ${message.content}');
});
}
}