Flutter即时通讯插件nim_core_v2的使用

发布于 1周前 作者 phonegap100 来自 Flutter

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

1 回复

更多关于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}');
    });
  }
}
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!