中秋礼物!开源即时通信GGTalk安卓版全新源码!
经过连续两个多月的努力(开发、调试、测试、改bug),我们终于赶在中秋国庆之前能把全新的GGTalk Android版本献给大家。
4年之前我们就推出了GGTalk Android的第一个版本,但是功能太简单,界面很粗糙,代码也很糟糕。后面了,因为一直忙着做项目,也没有太多时间去完善它。
很多使用GGTalk的朋友经常问新的Android版什么时候出来,我们也是不好意思地一拖再拖,到了今年7月份,终于再也拖不下去了,必须要发布一个功能相对完整的版本,才能对得住关注的朋友们。
终于,在今天GGTalk 7.0 对应的安卓全新版本终于和小伙伴们见面了,它与刚发布的GGTalk 7.0 的PC客户端可以是互通的,因此它当然也就可以与我们PC端相互通信,相互聊天了。下面我们先来看看它的真面目吧!
( 想要直接下载GGTalk Android全新源码的朋友请点击:源码下载中心)
一、GGTalk 安卓版截图

二、源码实现
接下来,我们概要的介绍一下GGTalk Android源码项目的结构,以及源码实现中比较重要和难以理解的部分,以方便大家能更快地上手GGTalk 安卓端源码。
1、项目结构

2、消息发送与接收
与服务端的通信交互还是与PC端一致,都是采用的ESFramework的通信框架来实现的。先创建一个客户端客户端引擎IRapidPassiveEngine,再调用引擎的initialize方法即可完成登录的操作。 代码如下
CustomizeHandler handler = new CustomizeHandler();
engine = RapidEngineFactory.CreatePassiveEngine();
engine.setEngineEventListener(GGApplication.getInstance());
engine.getBasicOutter().addBasicEventListener(GGApplication.getInstance());
LogonResponse resp = engine.initialize(getUserName, getPassWord, host, port, handler, getApplication());
登录成功后的消息都是在GGApplication这个类中收到并处理,主要有如下2个回调方法
/**
* 对方通过engin.sendMessage()方法发送的消息,会进入到该回调中
* */
@Override
public void messageReceived(String sourceUserID, int messageType, byte[] message, String tag) {
switch (ContractType.getContractTypeByCode(messageType)) {
case CHAT:
try {
RichChatMessage richChatMessage = new RichChatMessage();
richChatMessage.deserialize(BufferUtils.wrappedBuffer(message));
EventBus.getDefault().post(new ChatEvent(tag, tag, richChatMessage, false));
GGApplication.getInstance().ringForMessage();
} catch (Exception e) {
e.printStackTrace();
}
break;
...
} /**
* 对方通过engin.ICustomizeOutter.send()方法发送的消息,会进入到该回调中
* */
@Override
public void handleInformation(String sourceUserID, int messageType, byte[] bytes) {
try {
switch (ContractType.getContractTypeByCode(messageType)) {
case UserStatusChanged:
UserStatusChangedContract userStatusChangedContract = new UserStatusChangedContract();
userStatusChangedContract.deserialize(bytes);
EventBus.getDefault().post(new UserStatusChanagedEvent(userStatusChangedContract.getUserID(), userStatusChangedContract.getStatus()));
break;
...
}
发送消息方式同样有2种:1. 直接通过engin.sendMessage,2.通过ICustomizeOutter接口发送 它们调用的方式都大同小异, 我们就以第一种方式来做介绍
public void sendChatMessage(String targetUserID, RichChatMessage message) {
byte[] msg = null;
try {
msg = message.serialize();
} catch (Exception ee) {
ee.printStackTrace();
}
this.engine.sendMessage(null, ContractType.CHAT.getType(), msg, targetUserID);
}
void sendMessage(String targerID, int type, byte[] data, String tag);
第一个参数 targerID 为接收者ID(null 表示接收者为服务端),第二个参数type 为消息类型,第三个参数data 为消息内容 序列化后的数据,第四个参数tag为附带的字符串(可为空字符串)
3、主要控件介绍
(1)视频控件:CameraSurfaceView、OMCSSurfaceView。
CameraSurfaceView:主要功能是显示本机的预览界面,通过ICamOpenOverCallback接口的回调注入到OMCS框架中
@Override
public void cameraHasOpened() {
try {
//预览camera所用holder,不可为null或是隐藏,否则不能从摄像头获取数据
SurfaceHolder holder = myView.getSurfaceHolder();
//觸發預覽事件
MultimediaManagerFactory.GetSingleton().startCameraPreview(holder);
} catch (Exception ex) {
ex.printStackTrace();
}
}
OMCSSurfaceView:主要功能是连接对方的摄像头并显示图像。使用起来也比较简单,我们只需要通过setOtherVideoPlayerSurfaceView将它注入到摄像头连接器CameraConnector 中就可以了,当cameraConnector调用其beginConnect方法时就会自动去连接对方的摄像头,并将图像内容显示到OMCSSurfaceView控件上。
CameraConnector cameraConnector = new CameraConnector();
OMCSSurfaceView otherView = (OMCSSurfaceView) findViewById(R.id.opposite_surface);
cameraConnector.setOtherVideoPlayerSurfaceView(otherView);
cameraConnector.setVideoUniformScale(true,true);
cameraConnector.beginConnect(uerid);
(2)音频连接器 MicrophoneConnector
这个就比较简单了,只需调用其beginConnect方法即可,这样就可以连接到对方的麦克风,监听对方的语音
MicrophoneConnector microphoneConnector = new MicrophoneConnector();
microphoneConnector.beginConnect(uerid);
(3)语音消息 AudioMessage
首先是初始化,并注册播放的回调方法
@Override
protected void onResume() {
super.onResume();
if (!MultimediaManagerFactory.GetSingleton().getAudioMessageController().isInitialized()) {
MultimediaManagerFactory.GetSingleton().getAudioMessageController().initialize();
MultimediaManagerFactory.GetSingleton().getAudioMessageController().setAudioMessageHandler(GGApplication.getInstance());
MultimediaManagerFactory.GetSingleton().getAudioMessageController().getAudioMessagePlayer().setAudioPlayerCallback(this);
}
} //region IAudioPlayerCallback 播放回调
@Override
public void playFinished(AudioMessage message) {
message.setAnimation(false);
// Log.i("ChatLVAdapter", "playFinished:"+message);
Message msg = mHandler.obtainMessage(1);
mHandler.sendMessage(msg);
} @Override
public void playInterrupted(AudioMessage message) {
message.setAnimation(false);
// Log.i("ChatLVAdapter", "playInterrupted:"+message);
Message msg = mHandler.obtainMessage(1);
mHandler.sendMessage(msg);
}
//endregion
录制和发送语音消息给对方,startCapture()方法开始采集,stopCapture()方法停止采集并返回已采集的AudioMessage对象,再通过send方法将 AudioMessage对象发送给指定的好友。
if (event.getAction() == MotionEvent.ACTION_UP) {
if (SDKUtil.checkConnection()) {
AudioMessage message = MultimediaManagerFactory.GetSingleton().getAudioMessageController().stopCapture();
if (message != null) {
//没有一秒不发送
if (message.spanInMSecs > 1000) {
ChatInfo info = getChatInfo(GGApplication.getInstance().getMySelf().getUserID(), message, true);
addChatinfoAndDisplay(info);
MultimediaManagerFactory.GetSingleton().getAudioMessageController().send(message, TalkingID);
} else {
ToastUtils.showShort(ChatActivity.this.getApplication(), "时间太短!");
}
}
}
buttonSpeak.setText("按住说话");
//发出采集数据,并展现再界面中
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (SDKUtil.checkConnection()) {
MultimediaManagerFactory.GetSingleton().getAudioMessageController().startCapture();
}
buttonSpeak.setText("松开结束");
}
接收语音消息,需要实现 IAudioMessageHandler 接口 ,并调用setAudioMessageHandler 方法注入到OMCS框架中,当收到其他好友发来的语音消息时就会触发 handleAudioMessage,我们只需在该方法内做相关接收消息的处理即可。
public interface IAudioMessageHandler {
void handleAudioMessage(AudioMessage var1);
}
@Override
public void handleAudioMessage(AudioMessage message) {
try {
EventBus.getDefault().post(new ChatEvent(message.creatorID, message.creatorID, message, false));
GGApplication.getInstance().ringForMessage();
} catch (Exception e) {
e.printStackTrace();
}
}
MultimediaManagerFactory.GetSingleton().getAudioMessageController().setAudioMessageHandler(GGApplication.getInstance());
语音消息的播放和停止,通过getAudioMessagePlayer()获取播放器,调用其play或stop 方法即可完成播放语音和停止播放的功能
IAudioMessagePlayer audioPlayer=MultimediaManagerFactory.GetSingleton().getAudioMessageController().getAudioMessagePlayer();
audioPlayer.play(audioMessage);
audioPlayer.stop();
语音消息页面关掉时,记住要释放语音消息控制器,不然会一直占用麦克风
MultimediaManagerFactory.GetSingleton().getAudioMessageController().dispose();
三、GGTalk Android 源码下载
最新源码下载以及部署说明文档,请转到这里。
注意:全新的GGTalk Android源码,要配合最新的GGTalk 7.0(服务端+PC端),才可以正常互通的。
________________________________________________________________________
欢迎和我探讨关于GGTalk的一切,我的QQ:2027224508,多多交流!
大家有什么问题和建议,可以留言,也可以发送email到我邮箱:2027224508@qq.com。
如果你觉得还不错,请粉我,顺便再顶一下啊
中秋礼物!开源即时通信GGTalk安卓版全新源码!的更多相关文章
- 开源即时通讯GGTalk 8.0发布,增加Linux客户端,支持在统信UOS、银河麒麟上运行!
GGTalk在2021年推出7.0后,经过一年多时间的开发,终于推出8.0版本,实现了Linux客户端. 这几年,信创国产化的势头越来越猛,政府事企业单位都在逐步转向使用国产OS.国产CPU.国产数据 ...
- 【转】可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
原文地址:http://www.cnblogs.com/justnow/p/3382160.html (最新版本:V6.0,2017.12.11 .即将推出Xamarin移动端版本,包括 Androi ...
- 即时通信系统中如何实现:全局系统通知,并与Web后台集成?【低调赠送:QQ高仿版GGTalk 5.1 最新源码】
像QQ这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告.或是一个新闻.或是一个公告等.在这里,我们将其统称为“全局系统通知”.很多使用GGTalk的朋友都建议我加上一个类似 ...
- 一款安卓ShowcaseView视图源码效果
该源码是从源码天堂那边转载过来的,大家可以看看一下吧啊,一款安卓ShowcaseView视图源码效果,非常不错的,特别是在做引导时使用. 源码下载地址:http://code.662p.com/vie ...
- PureMVC(JS版)源码解析:总结
PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写博客的过程中得到了些提升.我也是第一次写系列 ...
- PureMVC(JS版)源码解析
PureMVC(JS版)源码解析:总结 PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写 ...
- HTML5与CSS3实例教程(第2版) 附源码 中文pdf扫描版
HTML5和CSS3技术是目前整个网页的基础.<HTML5与CSS3实例教程(第2版)>共分3部分,集中讨论了HTML5和CSS3规范及其技术的使用方法.这一版全面讲解了最新的HTML5和 ...
- 点菜网---Java开源生鲜电商平台-技术选型(源码可下载)
点菜网---Java开源生鲜电商平台-技术选型(源码可下载) 1.内容简介 点菜网目前选用的是最流行的微服务架构模式,采用前后端分离的开发模式,具备高可用,高负载,支持千万级别的数据量的请求. 2. ...
- 1-开发共享版APP(源码介绍)-BUG修复
这一系列文章将介绍APP的源码,这一节作为所有BUG问题修复! https://www.cnblogs.com/yangfengwu/category/1512162.html //开发共享版A ...
随机推荐
- 初识ABP vNext(6):vue+ABP实现国际化
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 语言选项 语言切换 注意 最后 前言 上一篇介绍了ABP扩展实体,并且在前端部分新增了身份认证管理和租户管理的菜单,在 ...
- CentOS7(Linux)源码安装Redis
介绍 项目中经常需要用到Redis做缓存数据库,可是还有小伙伴不会在Linux上安装Redis,毕竟我们开发的项目都是要在服务器上运行的,今天就来讲讲如何在CentOS7环境使用源码进行安装Redis ...
- log4j升级到log4j2
log4j升级到log4j2 1.导入依赖 log4j2应尽量使用同一版本,否则可能出现不兼容的情况 <!-- log4j2 start --> <!-- log4j-1.2-api ...
- 【译】Introducing “Web Live Preview”
如果你开发的应用有 UI,你可能经历开发->编译->测试->修改->编译->测试的循环.根据所使用的框架或技术,有些可以改善这一流程,比如 edit-and-contin ...
- ES5和ES6的继承对比
ES5的继承实现,这里以最佳实践:寄生组合式继承方式来实现.(为什么是最佳实践,前面有随笔讲过了,可以参考) function Super(name) { this.name = name; } Su ...
- Laravel Reponse 响应客户端
Laravel Response 响应客户端 本篇文章逻辑较长,只说明和响应生命周期相关的必要代码. 本文主要内容顺序为: 1.执行上文管道中的then方法指定的闭包,路由的分发 2.在路由器中(Ro ...
- 利用GetPrivateProfileString读取配置文件(.ini)
利用GetPrivateProfileString读取配置文件(.ini) 配置文件中经常用到ini文件,在VC中其函数分别为: 写入.ini文件:bool WritePrivateProfileSt ...
- 2020最新Servlet+form表单实现文件上传(图片)
servlet实现文件上传接受 这几天学了一点文件上传,有很多不会,在网查了许多博客,但是最新的没有,都比较久了 因为我是小白,版本更新了,以前的方法自己费了好久才弄懂,写个随笔方便以后查找 代码奉上 ...
- HDU-1754-I Hate It(单点更新+区间查询)
很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有 ...
- Activiti7 学习总结
什么是工作流? 就是通过计算机对业务流程进行自动化处理,实现多个参与者按照预定义的流程去自动执行业务流程 什么是Activiti? Activiti是一个工作流引擎,开源的架构,基于BPMN2.0标准 ...