写点什么

玩转 OpenHarmony 社交场景:即时通讯平台

  • 2023-01-03
    上海
  • 本文字数:3664 字

    阅读完需:约 12 分钟

玩转OpenHarmony社交场景:即时通讯平台

一、简介

本样例是基于即时通讯(Instant messaging,简称 IM)服务实现的 OpenAtom OpenHarmony(简称“OpenHarmony”)应用,允许两人或多人使用互联网即时地传递文字、图片、文件、语音、emoji 等讯息,可应用于各类聊天场景,为人们带来更加及时高效的通讯体验。


此外即时通讯平台具备较高的定制化特点,适用于多种行业,客户可以根据自己的需求来定制,实现即时通讯的内部私有化。


设备端:DAYU200(RK3568)开发板,OpenHarmony 3.1 release 系统。



二、即时通讯实现原理



想要实现多个设备之间的无障碍即时通讯,需要多台终端设备、终端应用和服务器配合一起使用。首先应该将终端应用安装到终端设备上,用户通过应用向服务器申请注册账号。随后,用户可以通过账号进行查找,添加其他好友,并向好友发送文字、图片、文件、语音、emoji 等讯息。用户发送的讯息会先送达服务器,由服务器判断其好友的状态(离线/在线),然后选择发送或者暂时缓存消息等操作。最后,好友的终端应用接收到消息。


实现即时通讯的设备需求:安装应用的终端设备、网络环境和云端服务器。


前提条件:用户将应用安装在终端设备上,并且拥有注册账号,且需要通讯的用户也成功注册了账号并且添加了好友。


通讯原理:用户在安装了应用的终端设备上编辑信息(文字、图片、文件、语音、emoji 等),通过网络将消息发送至云端服务器。当对方用户在线时,云端服务器将把消息推送给对方用户,对方用户安装了应用的终端设备也将接收到信息。当对方用户不在线时,信息将被暂时缓存在云端服务器。

三、4 步实现多人即时通讯

(1) 通讯功能通讯功能是通过 TCP 协议实现的,我们将通讯接口 connect()、send()、receive()的实现放置在 CPP 文件中,通过 NAPI 的方式对 JS 层暴露接口。


• connect():客户端和服务器建立连接;

• send():消息发送功能

• receive():消息接收功能;


//建立TCP连接if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {    napi_create_int32(env, 0, &result);} else {    napi_create_int32(env, 1, &result);    OH_LOG_INFO(LOG_APP,"C++ 接收线程启动");    startRec();} //发送消息if(send(sock_cli, data, strlen(data),0) == -1) {    OH_LOG_INFO(LOG_APP,"zjf == send() : -1");    napi_create_int32(env, 0, &result);} else {    OH_LOG_INFO(LOG_APP,"zjf == send() : !-1");    napi_create_int32(env, 1, &result);}//接收消息getStep(queue0,sharedMessage); //取出一条消息const char *c_s=sharedMessage.c_str();//换为char*形式处理napi_value result;napi_create_string_utf8(env, c_s, sharedMessage.length(), &result);std::string().swap(sharedMessage);//清空字符串
复制代码


(2) 文件消息的发送与接收



文件转发是即时通讯办公场景下的重要功能。样例中的文件功能支持文件消息的发送、接收和下载。用户通过点击聊天界面的“+”按钮,选择“文件”按钮,完成本地文件的浏览,随后可以选择是否将文件发送给好友。这个功能的实现包括三个步骤:(1)文件的选择;(2)文件上传到服务器;(3)文件的接收。

• 文件上传


//文件的选择let file1 = {filename: this.$app.$def.uid +'-'+ FILE_URL, name: 'file', uri: FILE_URL, type:fileType }let fileId = this.guid();let data = {};let header = { "filename": this.selectedFileName.toString()};//文件上传到服务器request.upload({ url: "http://" + this.$app.$def.ip +"/file/fileUpload?fileSignature=" + fileId + "&uid=" +this.$app.$def.uid + "&fileType=" +this.$app.$def.chatData[this.idx].unRead, header: header, method: "POST", files: [file1], data: [data] }).then((data) => {  uploadTask = data;  uploadTask.on('headerReceive', function callback(headers){  _this.socketSendFile(fileId, timestamp);  });}).catch((err) => {  console.error('fileSelect=====Failed to request the upload. Cause: ' + JSON.stringify(err));})//文件的接收let downloadConfig = {  //下载参数            url: fileUrl,             header: {},             enableMetered: true,             enableRoaming: true,            filePath: '/data/storage/el2/base/haps/entry/files/' + downloadFileName,            networkType: request.NETWORK_WIFI}request.download(downloadConfig, (err, data) => {        if (err) {            return;        }        downloadTask = data;        //下载完成        downloadTask.on('complete', function callback() {                prompt.showToast({                   message: '下载文件成功!',                   duration: 1000,                });        });
复制代码


(3) 语音消息的发送与接收



用户通过点击聊天界面的录制按钮,完成语音的录制,随后可以选择是否将语音发送给好友。这个功能的实现包括三个步骤:(1)语音的录制;(2)语音上传到服务器;(3)语音的接收。

图片消息的发送与语音消息的发送步骤相同,文章中不再赘述。


//语音录制startRecorder(config, callback) {    if (typeof (this.audioRecorder) !== 'undefined') {        this.audioRecorder.on('prepare', () => {        this.audioRecorder.start()    })        this.audioRecorder.on('start', () => {            callback()        })        this.audioRecorder.prepare(config)     } else {        logger.info(`${TAG} case failed, audiorecorder is null`)    }}
//录制好的语音文件的位置let srcPath = 'internal://cache/' + this.mainData.file + '.wav'let file1 = { filename: this.$app.$def.uid +'-'+ this.mainData.path, name: 'audio', uri: srcPath, type: "wav" };
//语音消息发送到服务器request.upload({ url: myurl, header: header, method: "POST", files: [file1], data: [data] }).then((data) => { uploadTask = data; uploadTask.on('headerReceive', function callback(headers){ _this.sendAudio(audioId) }); uploadTask.on('progress', function callback(uploadedSize, totalSize) { console.info("dialogPages=====upload totalSize:" + totalSize + " uploadedSize:" + uploadedSize); }); }).catch((err) => { console.error('dialogPages=====Failed to request the upload. Cause: ' + JSON.stringify(err)); })//语音的接收let downloadConfig = { //下载参数 url: item.content.path, header: {}, enableMetered: true, enableRoaming: true, filePath: filePath, networkType: request.NETWORK_WIFI } let downloadTask; let _this = this request.download(downloadConfig, (err, data) => { if (err) { return; } downloadTask = data; //下载完成 downloadTask.on('complete', function callback() { let audio = { content: { path: filePath } } _this.playAudio(audio) });
复制代码


(4) emoji 消息的发送与接收



emoji 是即时通讯软件不可缺少的一部分,可以更加生动地表现用户的聊天情感。在样例中,用户通过点击聊天界面的 emoji 按钮,即可找到目前应用内支持的所有样式的 emoji,随后可以选择具体样式并将其发送给好友。


//引入emoji第三方组件<element name="emojiExpression" src="../../common/components/emojiExpression/emojiExpression.hml"></element>
//第三方组件的展示布局<div id="moreContainer" if="{{showFace}}"> <div id="moreOneLine"> <div class="moreFillGap" style="flex: 1 1;"></div> <text style="left: 25fp; top: 10fp;">所有表情</text> <emojiExpression></emojiExpression> <div class="moreFillGap" style="flex: 1 1;"></div> </div></div>
复制代码


四、即时通讯功能总结

本样例是基于 OpenHarmony 实现的即时通讯应用,目前已经支持文字、图片、文件、语音、emoji 等讯息的快速发送与接收。除此之外还实现了好友的添加与删除、黑名单、安全登录、私聊/群聊、个人信息设置(二维码/头像等)等功能的全方面支持。

代码地址https://gitee.com/isrc_ohos/instant-message_ohos

五、相关参考链接

样例源码https://gitee.com/isrc_ohos/instant-message_ohos

OpenHarmony 知识体系工作组https://gitee.com/openharmony-sig/knowledge



用户头像

OpenHarmony开发者官方账号 2021-12-15 加入

OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,基于开源的方式,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展

评论

发布
暂无评论
玩转OpenHarmony社交场景:即时通讯平台_OpenHarmony_OpenHarmony开发者_InfoQ写作社区