一. 开发环境

开发工具:DevEco Studio 5.1

 

开发语言:ArkTS

 

测试手机:华为 Mate 70

 

二. Demo 实现的功能

  本文ESFramework的鸿蒙版Demo演示了以下功能:

 

(1)客户端用户上下线时,通知其他在线用户。

(2)当客户端与服务端网络断开时,进行自动重连,当网络恢复后,重连成功。

(3)所有在线用户之间可以进行文字聊天。

(4)文件传送。

(5)消息同步调用。

(6)重登陆模式。当同名的用户登陆时,会把前面的用户挤掉。

 

  这里有该Demo运行的效果 演示视频。

 

  文末有该Demo鸿蒙端实现的源码,下载源码后,对照着这篇文章看,会更容易理解。   

 

三. Harmony鸿蒙客户端实现说明

  源码解压后,在DevEco Studio中打开Demo项目,其结构如下所示:

 

1. 文件目录结构

  image

 

2.定义信息类型

     在本demo中,我们定义5个信息类型,分别表示文字聊天消息(直接发送给对方),文字聊天消息(由服务端转发),图片消息、撤回消息,以及客户端同步调用服务端。其定义如下:

 

复制代码

enum InformationTypes{

  /// 文字(表情)聊天信息

  TextChat = 0,

  /// 文字(表情)聊天信息 (由服务端转发给消息接收方)

  TextChat4Transit = 1,

  /// 图片聊天信息

  ImageChat = 2,

  /// 收到消息发送者 撤回消息请求

  RecallMsg = 3,

  /// 客户端异步调用服务端

 ClientSyncCallServer = 4,

}

复制代码

3.实现自定义信息处理器

      客户端的utils里的customizeHandler实现了ICustomizeHandler接口,其主要实现HandleInformation方法,来处理收到的聊天信息。

 

handleInformation(sourceUserID: string, informationType: number, info: number[]): void{

   ......

}

4.index.ets 登录页

  登录页的样式如图所示:

 

  Screenshot_2025-10-16T173824

 

   输入ip、账号、密码后,点击登录,输入的数据会用于初始化RapidPassiveEngine以登录。代码如下:

 

复制代码

//通过@Provide标记engine并定义,可以将engine与后代组件双向同步

@Provide('engine') engine:RapidPassiveEngine|null = null

//通过@State将数据设置为响应式的数据

@State ip:string = '192.168.0.244'

@State userId:string = '101'

@State pwd:string = '12'

 

//点击登录按钮

Button('登录',{ type: ButtonType.Normal }).onClick(()=>{

     //新建一个ESFramework引擎

     this.engine = new RapidPassiveEngine()

    //通过initialize方法,将登录的ip账号密码传进ESFramework

    this.engine.initialize(this.userId, this.pwd ,this.ip,

                      4530,customizeHandlers,(res)=>{

                         ......

   })

})

复制代码

5.home.ets 好友/功能页

  好友页里实现了好友列表的展示,收到消息后会将消息展示在好友名下方,好友页样式图如下:

 

  Screenshot_2025-10-17T084257

 

  当用户登录成功后,便可以从服务器获取所有在线联系人,然后客户端只需要处理这些信息即可渲染页面,处理信息代码如下:

 

复制代码

//创建一个User接口

export interface User{

  username:string,

  headImg:string,

  clientType:ClientType

}

 //在线用户列表

  @State userList:Array<User> = []

 

      //登录的时候,直接通过新建的引擎获取服务器里所有的在线成员,res为所有在线成员数组

      this.engine.ContactsOutter.getAllOnlineContacts((res:Array<string>)=>{

        //在这里添加用户列表

         ......

      })

       //监听联系人上线事件

       this.engine.ContactsOutter.event["ContactsDeviceConnected"] =()=>{

       //如果有联系人上线,将会进入这个函数

       ......

}

复制代码

 用户列表渲染主要代码如下:

 

复制代码

      Column() {

          //使用List来渲染用户列表

        List() {

          //通过foreach获取到每一个用户的信息

          ForEach(this.userList, (item:User) => {

            ListItem() {

              Flex({direction:FlexDirection.Row,alignItems:ItemAlign.Center}){

                Image(item.headImg)

                Flex({direction:FlexDirection.Column,justifyContent:FlexAlign.SpaceBetween}){

                  Text(`${item.username}`)

                }

              }

            }

          })

        }

      }

复制代码

6. chat.ets 聊天页

  当有联系人向我发送消息,消息各项信息会进入已经实现的customizeHandler里的handleInformation里,客户端处理这些信息即可渲染画面,聊天页的样式如图所示:

 

  Screenshot_2025-10-13T094515

 

  处理相关代码如下:

 

复制代码

//在utils.ets文件里的customizeHandler类里,需要设置信息处理回调函数,外部才能通过传一个callback获取到收到消息的信息

private handleInformationCallback ?: Function;

//设置信息处理回调函数

  setHandleInformationCallback(callback : Function) : void {

  this.handleInformationCallback = callback;

  }

//处理来自其他用户的信息(包括大数据块信息)

   handleInformation(sourceUserID: string, informationType: number, info: number[]): void {

   if (this.handleInformationCallback) {

//将收到的信息传递到信息处理回调函数里

    this.handleInformationCallback(sourceUserID, informationType,util.getStr(info))

    }

  }

 

//在index.ets里

//设置聊天记录字典,键为用户id,值为聊天记录数组对象,message为聊天记录数据接口。

OrayDic为ESFramework内置的设置字典的方法

@Provide('userMessages') userMessages: OrayDic<string, Array<Message>> = new OrayDic();

//获取自定义消息处理器

const customizeHandlers = new customizeHandler()

//设置消息的监听

customizeHandlers.setHandleInformationCallback((sendID:string,informationType:number,chatInfo:string)=>{

//收到的文字图片信息都会进入这里,在这里处理聊天记录

  ......

})

复制代码

  聊天记录主要渲染代码如下:

 

复制代码

Column(){

          //通过List渲染聊天记录

          List(){

            //通过ForEach来获取每一个聊天信息

            ForEach(this.currentUserMessages,(item:Message)=>{

              ListItem(){

                Column(){

                  //文字信息

                  if(item.informationType == InformationTypes.TextChat || item.informationType == InformationTypes.TextChat4Transit){

                    //对方普通文字消息

                    if(item.SpeakerID == this.user?.username){

                      ......

                    }

                     //我方普通文字信息

                      else{

                     ......

                  }

                  //图片信息

                  if(item.informationType == InformationTypes.ImageChat) {

                      //对方图片信息

                    if(item.SpeakerID == this.user?.username) {

                      ......

                    }

                  //我方图片消息

                  else{

                      ......

                  }

                  //文件信息

                  if(item.informationType == InformationTypes.File){

                    //对方文件消息

                    if(item.SpeakerID == this.user?.username){

                      ......

                    }

                  //我方文件信息

                  else{

                      ......

                  }

                  //撤回信息

                  // if(item.informationType === InformationTypes.RecallMsg)

                  if(item.informationType == InformationTypes.RecallMsg) {

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐