nim_core_v2 10.5.0 copy "nim_core_v2: ^10.5.0" to clipboard
nim_core_v2: ^10.5.0 copied to clipboard

A Flutter plugin for NetEase IM SDK on Android, iOS and Windows.

example/lib/main.dart

// 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;

import 'package:yunxin_alog/yunxin_alog.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 chatroomId1 = '123456789';

  static const teamId = '35079835747';

  V2NIMChatroomClient? chatroomClient;

  final subsriptions = <StreamSubscription>[];

  final chatroomSubsriptions = <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 providerToken = TextEditingController();

  TextEditingController providerExtension = TextEditingController();

  TextEditingController providerTimeout = TextEditingController();

  TextEditingController reConnectEditingController = TextEditingController();

  //动态token
  String syncToken = "";

  @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;
      });
      _copyResources();
    }

    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()}';
      });
    }));

    subsriptions
        .add(NimCore.instance.conversationService.onSyncFailed.listen((e) {
      print('conversationService##onSyncFailed: ');
      setState(() {
        loginListener =
            loginListener + '\n conversationService##onSyncFailed: ';
      });
    }));

    subsriptions.add(NimCore.instance.teamService.onSyncFailed.listen((e) {
      print('teamService##onSyncFailed: ');
      setState(() {
        loginListener = loginListener + '\n teamService##onSyncFailed: ';
      });
    }));

    _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
  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 providerToken.text;
    };

    NimCore.instance.loginService.loginExtensionProvider =
        (String accountId) async {
      print('dart loginExtensionProvider');
      return providerExtension.text;
    };

    NimCore.instance.loginService.setReconnectDelayProvider((int time) async {
      print('dart setReconnectDelayProvider');
      return int.parse(providerTimeout.text);
    });

    final loginResult = await NimCore.instance.loginService.login(
        accountEditingController.text, passwordEditingController.text, options);
    print('login syncToken result: $loginResult');
  }

  ///发送消息并修改
  void sendMessageAndModify() async {
    NimCore.instance.messageService.onReceiveMessagesModified.listen((event) {
      print(
          'onReceiveMessagesModified: ${event.length} data = ${event[0].toJson()}');
    });

    final textMessage =
        (await MessageCreator.createTextMessage('test text message')).data;
    final conversationId =
        (await NimCore.instance.conversationIdUtil.teamConversationId(teamId))
            .data!;
    if (textMessage != null) {
      final sendMessageResult = await NimCore.instance.messageService
          .sendMessage(message: textMessage, conversationId: conversationId);
      if (sendMessageResult.isSuccess) {
        final sentMessage = sendMessageResult.data!.message!;
        final params = NIMModifyMessageParams(text: 'test text message modify');
        NimCore.instance.messageService
            .modifyMessage(sentMessage, params)
            .then((result) {
          print('modifyMessage result: ${result.data?.toJson()}');
        });
      }
    }
  }

  //创建聊天室并进入
  void createChatroom() async {
    chatroomClient = (await V2NIMChatroomClient.newInstance()).data;
    print('chatroom: ${chatroomClient?.instanceId}');

    if (chatroomClient != null) {
      chatroomClient!.addChatroomClientListener();

      chatroomSubsriptions.addAll([
        chatroomClient!.onChatroomEntered.listen((event) {
          print('ChatroomClient:onChatroomEntered');
        }),
        chatroomClient!.onChatroomExited.listen((event) {
          print('ChatroomClient:onChatroomExited');
        })
      ]);

      final links = await NimCore.instance.loginService
          .getChatroomLinkAddress(chatroomId1);

      Alog.d(
          tag: 'ChatroomClient',
          content: 'enter result:${links?.isSuccess} data ${links?.data}');

      final enterParams = V2NIMChatroomEnterParams(
          authType: NIMLoginAuthType.authTypeDefault,
          accountId: account,
          token: token);

      chatroomClient!.linkProvider =
          (int instanceId, String roomId, String accountId) async {
        return links.data!;
      };

      final enterResult = await chatroomClient!.enter(chatroomId1, enterParams);

      print(
          'enter result:${enterResult?.isSuccess} data ${enterResult?.data?.toJson()}');

      Alog.d(
          tag: 'ChatroomClient',
          content:
              'enter result:${enterResult?.isSuccess} data ${enterResult?.data?.toJson()}');

      final chatroomInfoResult = await chatroomClient?.getChatroomInfo();

      print(
          'chatroomInfo result: ${chatroomInfoResult?.isSuccess} data ${chatroomInfoResult?.data?.toJson()}');

      Alog.d(
          tag: 'ChatroomClient',
          content:
              'chatroomInfo result: ${chatroomInfoResult?.isSuccess} data ${chatroomInfoResult?.data?.toJson()}');
    }
  }

  //添加监听
  void chatroomServiceListener() async {
    final addresult =
        await chatroomClient?.getChatroomService().addChatroomListener();

    chatroomSubsriptions.addAll([
      chatroomClient!.getChatroomService().onReceiveMessages.listen((event) {
        print('getChatroomService:onReceiveMessages');
      }),
      chatroomClient!.getChatroomService().onSendMessage.listen((event) {
        print('getChatroomService:onSendMessage ${event.message?.toJson()}');
      }),
      chatroomClient!
          .getChatroomService()
          .onSendMessageProgress
          .listen((event) {
        print(
            'getChatroomService:onSendMessageProgress  ${event.messageClientId} process ${event.progress}');
      }),
    ]);
  }

  void sendChatroomTextMessage() async {
    final message = (await V2NIMChatroomMessageCreator.createTextMessage(
            'test text chatroom message'))
        .data;

    final chatroomService = chatroomClient?.getChatroomService();

    if (message != null) {
      V2NIMSendChatroomMessageParams params = V2NIMSendChatroomMessageParams();
      final messageSender = await chatroomService?.sendMessage(message, params);
      print(
          'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
      Alog.d(
          tag: 'ChatroomService',
          content:
              'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
    }
  }

  void sendChatroomVideoMessage() async {
    final videoPath = Platform.isAndroid
        ? (await getExternalStorageDirectory())!.path + "/test.mp4"
        : (await getApplicationDocumentsDirectory()).path + "/test.mp4";

    if (!File(videoPath).existsSync()) {
      print('File $videoPath 不存在');
    }

    final message = (await V2NIMChatroomMessageCreator.createVideoMessage(
            videoPath,
            duration: 70000,
            width: 102,
            height: 150))
        .data;

    final chatroomService = chatroomClient?.getChatroomService();

    if (message != null) {
      V2NIMSendChatroomMessageParams params = V2NIMSendChatroomMessageParams();
      final messageSender = await chatroomService?.sendMessage(message, params);
      print(
          'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
      Alog.d(
          tag: 'ChatroomService',
          content:
              'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
    }
  }

  void sendChatroomImageMessage() async {
    final imagePath = Platform.isAndroid
        ? (await getExternalStorageDirectory())!.path + "/test.jpg"
        : (await getApplicationDocumentsDirectory()).path + "/test.jpg";

    if (!File(imagePath).existsSync()) {
      print('File $imagePath 不存在');
    }

    final message = (await V2NIMChatroomMessageCreator.createImageMessage(
            imagePath,
            width: 0,
            height: 0))
        .data;

    final chatroomService = chatroomClient?.getChatroomService();

    if (message != null) {
      V2NIMSendChatroomMessageParams params = V2NIMSendChatroomMessageParams();
      final messageSender = await chatroomService?.sendMessage(message, params);
      print(
          'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
      Alog.d(
          tag: 'ChatroomService',
          content:
              'messageSender: ${messageSender?.isSuccess} data ${messageSender?.data?.toJson()}');
    }
  }

  void sendChatroomAudioMessage() async {
    final audioPath = Platform.isAndroid
        ? (await getExternalStorageDirectory())!.path + "/test.mp3"
        : (await getApplicationDocumentsDirectory()).path + "/test.mp3";

    if (!File(audioPath).existsSync()) {
      print('File $audioPath 不存在');
    }

    final message = (await V2NIMChatroomMessageCreator.createAudioMessage(
            audioPath,
            duration: 6000))
        .data;

    final chatroomService = chatroomClient?.getChatroomService();

    if (message != null) {
      V2NIMSendChatroomMessageParams params = V2NIMSendChatroomMessageParams();
      final audioMessageSender =
          await chatroomService?.sendMessage(message, params);
      print(
          'audioMessageSender: ${audioMessageSender?.isSuccess} data ${audioMessageSender?.data?.toJson()}');
      Alog.d(
          tag: 'ChatroomService',
          content:
              'audioMessageSender: ${audioMessageSender?.isSuccess} data ${audioMessageSender?.data?.toJson()}');
    }
  }

  void getMessageList() async {
    final chatroomService = chatroomClient?.getChatroomService();
    if (chatroomService != null) {
      final option = V2NIMChatroomMessageListOption(limit: 2);
      final messageList = (await chatroomService.getMessageList(option));
      if (messageList.data != null) {
        messageList.data!.forEach((message) {
          print('messageList : ${message.toJson()}');
        });
      }
    }
  }

  void _copyResources() async {
    // copy image
    var bytes = await rootBundle.load("resources/test.jpg");
    Directory? documentDir = await getApplicationDocumentsDirectory();
    File tempFile = new File("${documentDir?.path}/test.jpg");
    if (!tempFile.existsSync()) {
      tempFile.createSync();
    }
    tempFile.writeAsBytes(
        bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));

    // copy mp3
    bytes = await rootBundle.load("resources/test.mp3");
    tempFile = new File("${documentDir?.path}/test.mp3");
    if (!tempFile.existsSync()) {
      tempFile.createSync();
    }
    tempFile.writeAsBytes(
        bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));

    // copy mp4
    bytes = await rootBundle.load("resources/test.mp4");
    tempFile = new File("${documentDir?.path}/test.mp4");
    if (!tempFile.existsSync()) {
      tempFile.createSync();
    }
    tempFile.writeAsBytes(
        bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));
  }

  @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'),
              TextField(
                controller: providerToken,
              ),
              Text('登录扩展'),
              TextField(
                controller: providerExtension,
              ),
              Text('登录重连延时回调'),
              TextField(
                controller: providerTimeout,
                keyboardType: TextInputType.number, // 弹出数字键盘
                inputFormatters: <TextInputFormatter>[
                  FilteringTextInputFormatter.digitsOnly // 只允许输入数字
                ],
              ),
              TextButton(
                  onPressed: () {
                    loginNormal();
                  },
                  child: Text('普通登录')),
              TextButton(
                  onPressed: () {
                    loginSync();
                  },
                  child: Text('特殊登录')),
              TextButton(
                  onPressed: () {
                    createChatroom();
                  },
                  child: Text('创建聊天室并进入')),
              TextButton(
                  onPressed: () {
                    chatroomServiceListener();
                  },
                  child: Text('添加聊天室服务')),
              TextButton(
                  onPressed: () {
                    sendChatroomTextMessage();
                  },
                  child: Text('发送消息')),
              TextButton(
                  onPressed: () {
                    sendChatroomImageMessage();
                  },
                  child: Text('发送图片消息')),
              TextButton(
                  onPressed: () {
                    sendChatroomVideoMessage();
                  },
                  child: Text('发送视频消息')),
              TextButton(
                  onPressed: () {
                    sendChatroomAudioMessage();
                  },
                  child: Text('发送语音消息')),
              TextButton(
                  onPressed: () {
                    getMessageList();
                  },
                  child: Text('拉取消息')),
            ],
          ),
        ),
      ),
    );
  }
}
copied to clipboard