通知设置 新通知
【领取见面礼】限量 100份 GeekOnline加油包!等你来拿 置顶
活动 • 雨山 回复了问题 • 62 人关注 • 62 个回复 • 2283 次浏览 • 2020-09-08 17:35
【社区精华|持续更新】收录本社区精华内容,手把手教学IM/RTC开发! 置顶
技术交流 • admin 发表了文章 • 8 个评论 • 281 次浏览 • 2020-12-07 14:41

本文收录了GeekOnline社区精华内容,希望帮助社区开发者学习IM+RTC知识,解答疑惑。赠人玫瑰,手有余香,如您有不错的内容需要收录,欢迎在在评论区投稿回复。
Android篇
解决融云 SDK 4.0 版本配置 https 导航报 SSLHandshakeException
融云即时通讯SDK集成 — 定制UI(一) ——会话界面小改动
融云即时通讯SDK集成 — 定制UI(二) ——添加自定义表情库
融云即时通讯SDK集成 — 定制UI(三) ——兼容Android Q
融云即时通讯SDK集成 — 国内厂商推送集成踩坑篇(Android平台)
融云 ConversationListFragment 会话列表添加头部布局
融云即时通讯SDK集成 — FCM推送集成指南(Android平台)
iOS篇
集成融云 IMLib 时,如何实现一套类似于 IMKit 的用户信息管理机制
干货分享——使用融云通讯能力库 IMLib 实现单群聊的阅读回执
Web篇
作为小白接融云 IM SDK 新路体验~
微信小程序集成融云 SDK (即时通讯) 集成必备条件
Web 端使用融云 SDK 集成实现滑动加载历史消息
融云IM SDK web 端集成 — 表情采坑篇
融云 Web SDK 如何实现表情的收发 ?
集成融云小程序 SDK 遇到的问题
使用融云 Web SDK 撤回消息
Web 端集成融云 SDK 如何发送正确图片消息给移动端展示?
融云 Web 播放声音 — Flash 篇 (播放 AMR、WAV)
融云 AMR(Aduio) 播放 AMR 格式 Base64 码音频
社区福利
【领取见面礼】限量 100份 GeekOnline加油包!等你来拿
【有奖调研】Geek Online 2020 编程挑战赛参赛调研
【征稿活动】Geek Online 社区第一期投稿激励计划已启动!
GeekOnline编程挑战赛
Geek Online 2020 编程挑战赛 GitHub 仓库
2 个月激烈角逐,15 支队伍突围决赛路演!Geek Online 2020 编程挑战赛完美收官!
一张图回顾 Geek Online 2020 编程挑战赛精彩瞬间!
“这些项目不是什么赚大钱的项目,但是它们足够有趣。”丨关于 Geek Online 2020 编程挑战赛,选手们如是说
融云 CTO 杨攀: Geek Online 2020 编程挑战赛 让开发者站上 C 位
【参赛攻略】你想了解的Geek Online 2020 编程挑战赛常见问题这里都有!
【融云集成常见问题整理】Geek Online 2020 编程挑战赛选手提问整理
求职招聘
持续更新....
【融云集成常见问题整理】Geek Online 2020 编程挑战赛选手提问整理 置顶
融云集成 • 梅川酷子 发表了文章 • 0 个评论 • 224 次浏览 • 2020-12-02 18:40

内容整理自Geek Online 2020 编程挑战赛群答疑内容,关于大赛请点击Geek Online 2020 编程挑战赛了解详情。如果您有IM/RTC开发,融云开发文档建议等技术问题欢迎留言讨论。
问题 1: 下载SDK如何选择?各大版本有什么区别?
问题 1 答案:使用最新版本 4.0 SDK ,新版 SDK 包含很多新功能并且会将历史版本遗留 Bug 进行修复,所以极力推荐使用新版 SDK 4.0+ 集成开发,下载地址:https://www.rongcloud.cn/downloads
问题 2 :开发环境和生产环境有什么区别?
问题 2 答案: 开发环境功能免费使用,但用户数有 100 个限制,生产环境无用户数限制,但需要付费,咱们的参赛同学使用开发环境集成就好
问题 3 :参赛过程中开发产生的费用怎么办?(注:本条仅限于参赛期间选手的参赛作品)
问题 3 答案:开发环境功能均可免费体验,遇到特殊情况可在战队群里向融云同学处理
问题 4 :小程序开发有什么注意事项?
问题 4 答案:
(1)需要在开发者后台小程序中开通,开通 30 分钟后生效
(2)小程序发布上线需要优先设置合法域名:https://docs.rongcloud.cn/v4/views/rtc/call/noui/quick/mini.html
(3)小程序特殊分类需要证书,例如社交小程序需要 ICP 证书,所以大家选择小程序分类时要提前注意是否需要证书
问题 5: 融云支持哪些平台?
问题 5 答案:支持 iOS、Android、Web、Flutter、uniapp、Electron,如果有 IoT 需求可以私信融云同学
问题 6: 如果遇到集成文档问题,怎么办?(也可以在本篇文章留言回复)
问题 6 答案:可直接在战队群里反馈至融云同学,欢迎大家对文档的改进提出宝贵建议,感谢
问题7:ios没上线 push怎么做?
问题7答案:在融云开发者后台 -> 应用 -> 开发环境可以设置
问题8:融云的RTC集成必须要集成IM?
问题8答案:RTC SDK 依赖于 IM SDK,一定要连接 IM 后再进行 RTC 相关的集成
问题9:融云新版SDK4.0版本和2.0版本对比有哪些升级?具体有哪些优化和提升?
问题9答案:4.0 SDK 是融云基于近几年的经验积累和沉淀进行的重构版,包含对架构、连接、重连、弱网等使用场景做了特殊优化,除核心能力优化外 4.0 SDK 还在持续发布新功能,例如:聊天室 KV 存储、会话置顶免打扰等
问题10:我想问一下,rongrtc的storage改动如何监听似乎rongclient设置接受到消息的onreceived回调不会触发。而改动storage 时是有设置第三个消息参数的,Sdk的debug会打印storage_set的,可以拦截不?
问题10答案:如果设置了第三个参数,会触发接收方的 RongRTC 实例的 Message received 监听
问题11:融云有没有小程序版的IM集成SDK?
问题11答案:有的,开发者后台开通小程序后可以直接下载小程序 IM SDK,开通位置:https://developer.rongcloud.cn/miniprogram/index/
问题12:弱弱的问一句,融云可否实现微信群机器人?现在微商盛行,想用融云做个自动问答的机器人客服 」
问题12答案:可以的,融云支持将消息路由的能力,消息路由到自己服务器后可以对接三方图文识别厂商
问题13:融云有内嵌到app的H5版本客服机器人吗?
问题14:不单独提供客服的,但 IM SDK 支持 H5 的
感谢各位选手的参与,Geek Online 2020 编程挑战赛 完美收官,关于大赛:
2 个月激烈角逐,15 支队伍突围决赛路演!Geek Online 2020 编程挑战赛完美收官!
“这些项目不是什么赚大钱的项目,但是它们足够有趣。”丨关于 Geek Online 2020 编程挑战赛,选手们如是说
一张回顾 Geek Online 2020 编程挑战赛精彩瞬间!
关于IM/RTC开发,融云开发文档建议等技术问题欢迎留言讨论
2 个月激烈角逐,15 支队伍突围决赛路演!Geek Online 2020 编程挑战赛完美收官! 置顶
技术交流 • 梅川酷子 发表了文章 • 0 个评论 • 253 次浏览 • 2020-10-27 09:59
【征稿活动】Geek Online 社区第一期投稿激励计划已启动! 置顶
活动 • 梅川酷子 发表了文章 • 3 个评论 • 491 次浏览 • 2020-08-27 19:40

为了回馈社区用户长期以来的支持,营造良好的社区技术氛围,鼓励更多开发者交流技术心得、分享技术实操方法及经验,创作更多优秀内容。特面向所有社区注册用户,举办第一期 Geek Online 社区投稿激励计划活动。
活动时间
征稿时间:8 月 27 日 – 10 月 31 日
评审时间:9、10 月每月最后一周进行
面向对象
Geek Online 社区所有注册用户
内容要求
对技术的介绍、产品的分析等技术类内容均可,也可以是个人实际操作的方法或经验总结,可供参考方向:
1、融云产品相关,选题包括:集成 IM 或 RTC 的使用体验、操作攻略、案例分享等。
2、结合市面上热度较高的事件/现象,从技术视角挖掘开发逻辑、产品解读等。
参赛规则
1、投稿需符合上述内容要求,图文并茂,排版美观,无错别字,代码规范。
2、在 Geek Online 社区发布文章参与,标题格式为【GeekOnline 投稿 | XXXXXXXXXX】
3、稿件字数在 500 字以上
5、投稿数量不限,但所有稿件内容必须为 2020 年 8 月 27 日后作者本人新发内容
6、投稿人社区账号头像、昵称、个人介绍需资料完善
7、稿件投递后 2 个工作日内完成初审,并通过社区消息、邮箱通知。
评分细则
1、每月底将对当月参赛稿件进行评比,满分 10 分。其中,
影响力 3 分,由社区内热度(阅读数)、互动量(点赞、评论数)加权计算;
专业性 7 分,由 Geek Online 技术专家及编辑组成的评审团,从文章实用性、创新性及代码规范度等方面综合评定给分。
2、我们鼓励投稿内容与融云产品相结合,对于此类稿件将给予社区置顶等曝光机会,增加文章影响力。
奖励
1、所有稿件通过初评,即可获得 Geek Online 加油包 1 份(内容发布 7 个工作日内发出)
2、月度评选后,根据得分,给予优秀稿件 200-1000 元京东购物卡奖励,并在社区公示。
3、优秀稿件,经编辑审核后,将安排在不限于公众号、社群及网媒中推广。
4、获奖作者,有机会加入社区特邀专栏作者计划,获得更高现金激励,并受邀参与融云各类开发者活动(线下/线上)
声明
1、在法律允许范围内,活动最终解释权归 Geek Online 社区所有。
2、参加活动的文章作者拥有著作权,Geek Online 社区、融云全媒体平台拥有使用权。
3、对于作者发布非原创内容或有争议内容所引起的一切后果,均由作者承担。欢迎社区用户举报,一经查实,作废处理。
融云 IMKit 音频录制参数
技术交流 • 王叫兽 发表了文章 • 0 个评论 • 36 次浏览 • 4 天前
场景:
使用融云自带的界面进行语音消息的播放。
自己进行音频录制。
使用的融云的
RCHQMessage
问题:
语音消息 iOS 和 Android 不互通,接收到消息之后无法播放。
解决方案:
经过与融云开发者的确认,使用时必须保证如下录制参数:
iOS AVAudioRecorder 录制参数如下设置:
AVFormatIDKey : @(kAudioFormatMPEG4AAC_HE),
AVSampleRateKey : @(44100.0),
AVNumberOfChannelsKey : @1,
AVEncoderBitRateKey : @(16000)
Android MediaRecorder 录制参数如下:
setAudioSamplingRate(44100);
setAudioEncodingBitRate(16000);
setAudioChannels(1);
setAudioSource(MediaRecorder.AudioSource.MIC);
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
其他一些内容的使用可以自己去官网文档搜索:
融云文档:https://docs.rongcloud.cn/v4/
融云会话页面刷新不及时问题
技术交流 • 徐凤年 发表了文章 • 0 个评论 • 36 次浏览 • 4 天前
项目用的融云 IMKit SDK,调试中发现收到消息的时候,不刷新,上拉一下才会显示。排查方法是直接使用 SDK 的会话页面,排除是子类代码的问题,替换后发现还是有此问题。后来和技术人员沟通发现是使用了 RCIMClient 中的初始化接口,这样会影响 UI 刷新的。替换为 RCIM 的初始化方法,问题解决!希望此文字可以帮助到后续开发者!
/*!
初始化融云SDK
@param appKey 从融云开发者平台创建应用后获取到的App Key
@discussion 您在使用融云SDK所有功能(包括显示SDK中或者继承于SDK的View)之前,您必须先调用此方法初始化SDK。
在App整个生命周期中,您只需要执行一次初始化。
@warning 如果您使用IMKit,请使用此方法初始化SDK;
如果您使用IMLib,请使用RCIMClient中的同名方法初始化,而不要使用此方法。
*/
- (void)initWithAppKey:(NSString *)appKey;
友情提示融云官网:(www.rongcloud.cn)
融云 Flutter IM SDK 解析
技术交流 • 木土走召 发表了文章 • 0 个评论 • 39 次浏览 • 4 天前
最近准备使用融云的 Flutter SDK,所以顺便记录一下。
融云 Flutter IM SDK 地址:传送门
融云的 Flutter SDK 是基于 融云 IMLib 层做的封装,封装了 IMLib 的部分接口提供给 Flutter 开发者使用。此文章只介绍了 Flutter 层做的一些操作。
目录结构
整体 SDK 的结构规规矩矩,核心内容参考红色箭头即可。
SDK 层包含 三个目录:android:此目录包含了和原生 SDK 交互的所有 Java 文件
ios:此目录包含了和原生 SDK 交互的所有 oc 文件
lib: 此目录为使用 dart 编写的 Flutter SDK 文件
其他目录:doc:主要是融云开发者提供的一些文档相关
example:是融云开发者基于此 SDK 提供的一个简单示例,整体较为简陋,且有细微 bug,仅供参考
FunctionList.md
是融云开发者提供的一个功能清单,
大体如下:
# RongCloud IM Flutter SDK 功能清单
## 连接
初始化
连接
断开连接
连接状态兼容
## 配置
设置服务器地址( im 服务;文件服务)
## 会话
获取会话列表,支持全量获取,分页获取
获取单个会话
删除指定会话
## 消息
当前仅支持 文本消息,语音消息,图片消息,小视频消息
收发消息(可以携带 pushContent)
自定义消息
获取批量本地历史消息
获取单条本地历史消息
获取批量远端历史消息
插入消息
删除批量本地消息
获取未读数
清除指定会话未读数
## 免打扰
设置会话免打扰
获取会话免打扰
## 会话置顶
设置会话置顶
备注:获取会话是可以获取到会话置顶状态
## 黑名单
加入黑名单
移除黑名单
获取黑名单列表
检查特定用户的黑名单状态
## 聊天室
加入聊天室
退出聊天室
获取聊天室信息
都是一些接口层的操作。
剩下的文件基本可以忽略。
解析
我们开始从 lib
目录开始分析
这两个文件是核心文件,我们所有的调用接口都在这里。
rong_im_client.dart
是最新版本的接口类,我们只关心这个即可。
rong_im_plugin.dart
是旧版本的接口类,已经废弃。
common_define.dart
是定义了 SDK 内使用的所有枚举和状态码。
method_key.dart
是定义了 Flutter SDK 和原生层进行交互时标识的唯一的常量字符串。
然后就是剩下的三个文件目录:
info
: 其实就是对象 model 类
message:
这个是 Flutter SDK提供的所有内置的消息类型,包括聊天室KV消息、合并消息、文件消息、GIF消息、图片消息、位置消息、撤回消息、引用消息、图文消息、视频消息、文本消息、语音消息。
其中有一个比较特殊的 dart 类就是 message_content.dart
, 这个类是所有消息的基类。
每个消息都需要继承此类,并复写里面的方法进行编解码。
util
: 这个目录就是一个工具目录。
message_factory.dart
主要是进行消息封装,字典转模型,模型转字典,根本原因我猜就是 Flutter 和 原生仅有的交互类型限制。
type_util.dart
:略
以上就是 SDK 在 Flutter 层做的所有的操作,内容整体不多,而且所有代码都是开源的,看看基本上都了解。
与原生层的交互
整体都是通过 invokeMethod
与原生进行通信的,后面的key 就是之前说的常量字符串,用来保证唯一性。
而在 iOS
和 Android
都提供了对应的定义。
并通过触发 iOS 和 Android 层对应的方法来进行处理。
原生层
Android:
整体核心的处理都在 RCIMFlutterWrapper.java
这个类处理了 dart 代码传递过来的数据,并与融云 IMLib 的 SDK 进行了处理。
iOS:
同样,iOS 的核心代码也都在 RCIMFlutterWrapper.m
这个类处理。具体内容大家可以自己看一下。
到此整个内容我们也就大体明白了。
整体看来其实就是 flutter 中 rong_im_client.dart
和 原生的两个 Wrapper
类做交互,其他的都是助攻。
整体看来不难,搞起~
融云文档:传送门
关于融云 SDK 在使用 p8 证书的坎坷~
技术交流 • 木土走召 发表了文章 • 0 个评论 • 32 次浏览 • 4 天前
新上的项目使用了融云的 IM SDK,但在项目集成 APNs 推送的时候,尝鲜使用了一下开发者后台的 p8 证书,此文记录使用 p8 的辛酸史~
P8 简介
官网给出了这种更 "快" 的推送通道: Establishing a Token-Based Connection to APNs,并且这个生成的这个 key 可以适用于当前账户的所有 APP,为开发人员省了不少力气。福音啊~
想想那一堆证书...... 脑阔痛!
辛酸史
起因是这样的,在融云开发者后台上传了 p8 之后,发现 debug 环境,一直无法收到推送,在经过和融云提供的推送文档进行严格的比对之后,发现没毛病啊~
最后终于在融云开发人员的帮助下找到了问题~,融云后台目前阶段只支持生产环境~ OMG,我打你信不~
区别
p8 是可以同时支持生产和测试环境的,那么为什么融云收不到呢~
让我们大胆猜测一下:
之前基于证书进行校验的时候,一套证书是基于开发者后台一个 AppKey 绑定的,那么我用了哪个 AppKey,后端就基于 AppKey 解析对应的证书,这样就可以发送到对应的 push 环境去了,那么问题来了?使用了 p8 之后,他怎么区分呢?
我也不知道~ 哈哈哈,但我猜测应该是没有解析都去走了生产环境,因为提示我环境不匹配~
苹果 APNs 服务
Development server: api.sandbox.push.apple.com:443
Production server: api.push.apple.com:443
融云 SDK 如何实现群组操作
技术交流 • 柠檬^ 发表了文章 • 0 个评论 • 30 次浏览 • 4 天前
融云 SDK 如何实现群组操作
背景
在集成融云 SDK 后,需要实现群组操作的消息通知。包括:
群创建、销毁通知
群公告通知
群人员加入、退出通知
群昵称修改通知
...
融云现有的 SDK 仅提供了 RCGroupNotificationMessage
,内部封装了几种简单的类型操作,且扩展性不强,无法完成现有的操作。
解决方案:
使用自定义消息重新来构建群组通知消息。
参考 sealtlak 中的 RCDGroupNotificationMessage
,也是单独对群组操作内容,重新进行了封装处理
/*!
群组通知消息
*/
@interface RCDGroupNotificationMessage : RCMessageContent
//操作名
@property (nonatomic, copy) NSString *operation;
//操作人
@property (nonatomic, copy) NSString *operatorUserId;
//操作对象
@property (nonatomic, strong) NSArray<NSString *> *targetUserIds;
//内容
@property (nonatomic, copy) NSString *message;
//获取摘要
- (NSString *)getDigest:(NSString *)groupId;
@end
这个类预定义了下面几种操作类型消息,具体内容可参考名字定义
extern NSString *const RCDGroupCreate;
extern NSString *const RCDGroupMemberAdd;
extern NSString *const RCDGroupMemberQuit;
extern NSString *const RCDGroupMemberKicked;
extern NSString *const RCDGroupRename;
extern NSString *const RCDGroupBulletin;
extern NSString *const RCDGroupOwnerTransfer;
extern NSString *const RCDGroupDismiss;
extern NSString *const RCDGroupMemberJoin;
extern NSString *const RCDGroupMemberManagerSet;
extern NSString *const RCDGroupMemberManagerRemove;
extern NSString *const RCDGroupMemberProtectionOpen;
extern NSString *const RCDGroupMemberProtectionClose;
.m 的实现还是按照自定义消息的实现进行处理。唯一有区别的是在获取摘要的方法,在这个方法中对消息内容进行了处理,根据操作名的不同,来对显示的内容进行各种适配。此处根据根据自己的业务进行修改。
- (NSString *)getDigest:(NSString *)groupId {
NSString *content;
//获取用户信息
NSString *operationName = [self getDisplayNames:@[ self.operatorUserId?self.operatorUserId:@""] groupId:groupId];
NSString *targetNames = [self getDisplayNames:self.targetUserIds groupId:groupId];
//是否当前用户操作
BOOL isMeOperate = NO;
if ([self.operatorUserId isEqualToString:[RCIMClient sharedRCIMClient].currentUserInfo.userId]) {
isMeOperate = YES;
}
//判断操作类型
if ([self.operation isEqualToString:RCDGroupCreate]) {
content =
[NSString stringWithFormat:NSLocalizedStringFromTable(isMeOperate ? @"GroupHaveCreated" : @"GroupCreated",
@"RongCloudKit", nil),
operationName];
} else if ([self.operation isEqualToString:RCDGroupMemberAdd]) {
if (self.targetUserIds.count == 1 && [self.targetUserIds containsObject:self.operatorUserId]) {
content = [NSString
stringWithFormat:NSLocalizedStringFromTable(@"GroupJoin", @"RongCloudKit", nil), operationName];
} else {
content = [NSString
stringWithFormat:NSLocalizedStringFromTable(isMeOperate ? @"GroupHaveInvited" : @"GroupInvited",
@"RongCloudKit", nil),
operationName, targetNames];
}
} else if ([self.operation isEqualToString:RCDGroupMemberJoin]) {
content =
[NSString stringWithFormat:NSLocalizedStringFromTable(@"GroupJoin", @"RongCloudKit", nil), operationName];
} else if ([self.operation isEqualToString:RCDGroupMemberQuit]) {
content = [NSString stringWithFormat:NSLocalizedStringFromTable(isMeOperate ? @"GroupHaveQuit" : @"GroupQuit",
@"RongCloudKit", nil),
operationName];
} else if ([self.operation isEqualToString:RCDGroupMemberKicked]) {
content =
[NSString stringWithFormat:NSLocalizedStringFromTable(isMeOperate ? @"GroupHaveRemoved" : @"GroupRemoved",
@"RongCloudKit", nil),
operationName, targetNames];
} else if ([self.operation isEqualToString:RCDGroupRename]) {
content = [NSString stringWithFormat:NSLocalizedStringFromTable(@"GroupChanged", @"RongCloudKit", nil),
operationName, self.targetGroupName];
} else if ([self.operation isEqualToString:RCDGroupDismiss]) {
content =
[NSString stringWithFormat:NSLocalizedStringFromTable(isMeOperate ? @"GroupHaveDismiss" : @"GroupDismiss",
@"RongCloudKit", nil),
operationName];
} else if ([self.operation isEqualToString:RCDGroupOwnerTransfer]) {
content = [NSString stringWithFormat:RCDLocalizedString(@"GroupHasNewOwner"), targetNames];
} else if ([self.operation isEqualToString:RCDGroupMemberManagerSet]) {
content = [NSString stringWithFormat:RCDLocalizedString(@"GroupSetManagerMessage"), targetNames];
} else if ([self.operation isEqualToString:RCDGroupMemberProtectionOpen]) {
content = RCDLocalizedString(@"openMemberProtection");
} else if ([self.operation isEqualToString:RCDGroupMemberProtectionClose]) {
content = [NSString stringWithFormat:RCDLocalizedString(@"closeMemberProtection"), operationName];
} else {
content = NSLocalizedStringFromTable(@"unknown_message_cell_tip", @"RongCloudKit", nil);
}
return content;
}
此外,还有一个获取名称的方法,用来维护用户信息。
- (NSString *)getDisplayNames:(NSArray<NSString *> *)userIds groupId:(NSString *)groupId