[已结束]  《全媒体客户中心管理》读书沙龙——武汉站
时间:2016-09-01 14:00
地点:武汉武昌区中北路汉街总部国际B座1504室
活动介绍:
8月3日,国内第一本“全媒体”客服学术著作《全媒体客户中心管理》读书沙龙将在包括北上广深等全国十大城市陆续举办。环信作为国内全媒体智能SaaS客服的倡领者一直致力于推动整个中国SaaS客服行业的发展,给企业提供最具效率和最佳用户体验的客服产品及服务。此次和客服行业权威媒体《客户世界》以及行业专家一起联合推出《全媒体客户中心管理》一书,环信提供了在全媒体客服领域包括产品技术和客户运营方面大量的最佳实践及成功案例。同时,环信参与了从前期图书主题的设定、相关最佳实践和成功案例的准备、中期文档图表的梳理、后期出版环节的编审和呈现,一直到各地读书沙龙的组织工作,目的也是推动整个SaaS客服行业和企业用户少走弯路,加速企业用户的信息化和用户体验进程,让呼叫中心(客户中心)提速迈向智能化和数据化时代。
活动时间:

演讲征集时间

2016-08-01 11:14 - 2016-08-23 11:10

活动举办时间

2016-09-01 14:00 - 2016-09-01 17:00

100% Complete

部分演讲主题展示:
  • 全媒体客户中心的规划、建设、运营与管理

    演讲嘉宾:张艳
    蜜芽服务副总裁  近20年客服中心管理经验,专注于企业自建呼叫中心运营管理、服务管理、会员精准营销。为多家企业搭建、重建呼叫中心,并成功推动呼叫中心从分布到集中、从服务到营销、从单渠道到全媒体转型。先后就职于携程旅行网、中青旅、中移动12580、红孩子、苏宁云商等企业, 现任蜜芽服务副总裁。

    从呼叫中心基础管理工作开始,多年来在电子商务类企业组织实战。张老师将她多年来的理论总结和实战经验加以提炼和归纳,汇集成为新书《全媒体客户中心管理》,期待对国内本行业管理者们的运营工作提供积极的帮助。
参加活动人员展示:
问演讲人:

问题标题: 环信

你的问题可能已经有答案

    问题补充 (选填):

     
    8
    回复

    收集基于环信SDK开发的开源项目 开源项目

    JuN_Yong Wang 回复了问题 • 10 人关注 • 5544 次浏览 • 2018-02-07 11:49 • 来自相关话题

    0
    评论

    2017环信八大开源项目源码放出:两个已获融资,单个20W+关注 开源项目

    beyond 发表了文章 • 1422 次浏览 • 2017-12-29 14:27 • 来自相关话题

    “这是一家极具极客范的公司”,来过环信公司的每一位客户都这么评价到。有着“连接人与人,连接人与商业”愿景的环信正在一步一步慢慢用技术和场景改变每个人的生活和工作。生有涯而知无涯,业有涯而心无涯,路漫漫其修远,“开源”当上下而求索!
     环信成立于2013年,公司数位联合创始人都是技术大牛出身,在Symbian,Nokia,Red Hat等知名IT公司都是开源项目的重度参与者,环信的基因便因此打上了“开源”的烙印,在2014年即创办了国内首个即时通讯云开源社区“IMGeek社区”,经过了3年多的深耕,2017年度在环信IMGeek社区涌现了数十个优质开源项目,其中两个开源项目目前已经拿到融资,更有一个项目获得了超过20W+的关注度,环信正通过即时通讯云PaaS平台和客服PaaS平台一步步完善自己的商业梦想,也在一步步的通过开源回馈自己的开发者和产业链上下游的小伙伴。




    环信公司前台一角
    2017年是企业服务丰收的一年,感谢伙伴们对环信一直以来的支持。18年伊始之际,我们总结了17年间基于环信开发者的八大开源项目,希望能对大家有所帮助。
     
    小马直播间-开源直播APP
     
    推荐理由:基于环信开发的开源直播应用,IMGeek收藏数量3W8,对于有直播需求的小伙伴们值得参考,教你从头开始开发一个移动端直播APP。
     
    互联网直播平台催生了一批批网红大咖,作为程序猿,我们绝不甘于委身幕后做搬砖工,我们一定要闪亮登场!!!做一个属于我们程序猿的IOS版直播平台~~




    应用截图
     实现功能:
    创建推流和拉流加速集成环信IM的聊天室功能集成UCloud的ULive直播云SDK在聊天室里集成推流(录制)和拉流(播放)功能
     相关链接:http://www.imgeek.org/article/825307904​ 

    Dolores-基于环信IM开发完整的企业通讯解决方案
     
    推荐理由:对企业而言,初选OA办公系统是为了满足需求,解决当下问题,由于OA办公系统的在公司运作流程中扮演的重要性,安全与隐私等问题急需未雨绸缪,“可定制”、“可私有化部署”的OA办公系统成为了更多企业的首选。
     
    公司想自己开发一套IM系统应该从哪里开始呢? 企业通讯录怎么保持同步呢? 企业通讯录的权限管理应该怎么做?




    Dolores海报
    相关链接:http://www.imgeek.org/article/825308805
     
    凡信-百尺竿头更进一步,2017凡信携直播、红包而来
     
    推荐理由:自凡信开源以来,更新了3个大版本,从基本聊天功能,到越来越多的开发者创建分支,累计收到了10W+的收藏,帮助了很多开发者进行开发即时通讯应用。
     
    已完成功能:
    单聊群聊朋友圈钱包直播红包




    项目运行效果图
    相关链接:http://www.imgeek.org/article/825307930
     
     Slack聊天机器人-环信客服版
     
    推荐理由:17年作为人工智能元年,聊天机器人(Chatbot)在各大行业的应用方兴未艾,国外包括Facebook Messenger、Slack等均引入了聊天机器人,所以毋庸置疑,聊天机器人将成为我们未来生活中不可或缺的一部分
    ,IMGEEK开源社区热心开发者&朝阳区群众“晨星桑”一言不合他就花2小时写了一个Slack的聊天机器人,您可以通过这个项目在Slack上对接客户服务,并且通过一些定制开发能够看见Slack用户的基本信息(比如:昵称、电话、团队名称等),并且可以二维码支付。
    相关功能:
    事件订阅初始化处理消息的事件把消息发送到移动客服处理OAuth回调把收到的消息发给Slack 用户
     
    相关链接:http://www.imgeek.org/article/825308711​ 
     
    泛聊-厉害了我的开发者,基于环信的开源高仿QQ项目
     
    推荐理由:聊天功能做到了极致,展示即时通讯基本功能的实现,包括注册登录,退出登录,联系人列表,添加好友,删除好友,收发消息,消息提醒等功能。




    项目运行效果图
    实现功能:
     环信SDK的集成与使用 MVP模式的运用 ORM数据库的集成与使用 模块化思想的运用
     相关链接:http://www.imgeek.org/article/825308542​ 
     
    Baby-开源私密社交应用
     
    推荐理由:私密社交APP,情侣、死党必备的一对一专属聊天应用。作者开发初期下载了市面上所有IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。使用环信EaseUi集成,基本上一天就能集成完毕。




    项目运行效果图
    实现功能:
    加入Tinker 热修复加入部分注释增加长按删除功能优化Rxbus订阅加载数据外国友人优化的一些细节增加了评论功能优化了相册加载把登陆注册事件换了个Zip操作符更符合流的思想
    相关链接:http://www.imgeek.org/article/825308850

    LITE-IM-环信webim的网页即时聊天

    推荐理由:你见过最酷炫的WEB聊天项目,LITE-IM不仅能够担当客户服务来使用,还可以用作你网站粘连客户、活跃社区的媒介,提升用户的使用率。




    项目运行效果图
    [b]实现功能:[/b]
    好友/群内的文字、表情、图片、文件 在线/离线消息发送和接收。查看群员列表。 面板内快速查找。 面板右键自定义事件 修改签名 自定义上传背景皮肤 搜索好友/群 添加好友/群 新建群 消息盒子展示
     相关链接:http://www.imgeek.org/article/825308961 
     
    VMTVCall-使用环信3.xSDK 在 TV 端集成音视频通话功能
     
    推荐理由:移动互联网方便了我们生活,移动端随时随地沟通成为了常态,今天我们推荐的是一个可以安装在电视机上进行视频通话的开源项目。




    项目运行效果图
     
    实现功能
    项目首次启动自动注册登录拨号盘实现历史通话记录 TODO视频通话功能(因为电视不需要语音通话以及最小化)视频通话的录制通话截图
     相关链接:http://www.imgeek.org/article/825308732
     
    end.
     
    生有涯而知无涯,业有涯而心无涯,路漫漫其修远,当上下而求索。未来,我们还将开源更多。
     
    环信IMGeek社区开源项目地址http://www.imgeek.org/code/
      查看全部
    “这是一家极具极客范的公司”,来过环信公司的每一位客户都这么评价到。有着“连接人与人,连接人与商业”愿景的环信正在一步一步慢慢用技术和场景改变每个人的生活和工作。生有涯而知无涯,业有涯而心无涯,路漫漫其修远,“开源”当上下而求索!

     环信成立于2013年,公司数位联合创始人都是技术大牛出身,在Symbian,Nokia,Red Hat等知名IT公司都是开源项目的重度参与者,环信的基因便因此打上了“开源”的烙印,在2014年即创办了国内首个即时通讯云开源社区“IMGeek社区”,经过了3年多的深耕,2017年度在环信IMGeek社区涌现了数十个优质开源项目,其中两个开源项目目前已经拿到融资,更有一个项目获得了超过20W+的关注度,环信正通过即时通讯云PaaS平台和客服PaaS平台一步步完善自己的商业梦想,也在一步步的通过开源回馈自己的开发者和产业链上下游的小伙伴。

    微信图片_20171229142123.jpg

    环信公司前台一角


    2017年是企业服务丰收的一年,感谢伙伴们对环信一直以来的支持。18年伊始之际,我们总结了17年间基于环信开发者的八大开源项目,希望能对大家有所帮助。
     
    小马直播间-开源直播APP
     
    推荐理由:基于环信开发的开源直播应用,IMGeek收藏数量3W8,对于有直播需求的小伙伴们值得参考,教你从头开始开发一个移动端直播APP。
     
    互联网直播平台催生了一批批网红大咖,作为程序猿,我们绝不甘于委身幕后做搬砖工,我们一定要闪亮登场!!!做一个属于我们程序猿的IOS版直播平台~~

    小马直播间.png

    应用截图


     实现功能:
    • 创建推流和拉流加速
    • 集成环信IM的聊天室功能
    • 集成UCloud的ULive直播云SDK
    • 在聊天室里集成推流(录制)和拉流(播放)功能

     相关链接:http://www.imgeek.org/article/825307904​ 

    Dolores-基于环信IM开发完整的企业通讯解决方案
     
    推荐理由:对企业而言,初选OA办公系统是为了满足需求,解决当下问题,由于OA办公系统的在公司运作流程中扮演的重要性,安全与隐私等问题急需未雨绸缪,“可定制”、“可私有化部署”的OA办公系统成为了更多企业的首选。
     
    公司想自己开发一套IM系统应该从哪里开始呢? 企业通讯录怎么保持同步呢? 企业通讯录的权限管理应该怎么做?

    89e5f4394605d1a330e558e46e7cc6b0.jpg

    Dolores海报


    相关链接:http://www.imgeek.org/article/825308805
     
    凡信-百尺竿头更进一步,2017凡信携直播、红包而来
     
    推荐理由:自凡信开源以来,更新了3个大版本,从基本聊天功能,到越来越多的开发者创建分支,累计收到了10W+的收藏,帮助了很多开发者进行开发即时通讯应用。
     
    已完成功能:
    • 单聊
    • 群聊
    • 朋友圈
    • 钱包
    • 直播
    • 红包

    凡信.png

    项目运行效果图


    相关链接:http://www.imgeek.org/article/825307930
     
     Slack聊天机器人-环信客服版
     
    推荐理由:17年作为人工智能元年,聊天机器人(Chatbot)在各大行业的应用方兴未艾,国外包括Facebook Messenger、Slack等均引入了聊天机器人,所以毋庸置疑,聊天机器人将成为我们未来生活中不可或缺的一部分
    ,IMGEEK开源社区热心开发者&朝阳区群众“晨星桑”一言不合他就花2小时写了一个Slack的聊天机器人,您可以通过这个项目在Slack上对接客户服务,并且通过一些定制开发能够看见Slack用户的基本信息(比如:昵称、电话、团队名称等),并且可以二维码支付。
    相关功能:
    • 事件订阅初始化
    • 处理消息的事件
    • 把消息发送到移动客服
    • 处理OAuth回调
    • 把收到的消息发给Slack 用户

     
    相关链接:http://www.imgeek.org/article/825308711​ 
     
    泛聊-厉害了我的开发者,基于环信的开源高仿QQ项目
     
    推荐理由:聊天功能做到了极致,展示即时通讯基本功能的实现,包括注册登录,退出登录,联系人列表,添加好友,删除好友,收发消息,消息提醒等功能。

    泛聊.png

    项目运行效果图


    实现功能:
    •  环信SDK的集成与使用
    •  MVP模式的运用
    •  ORM数据库的集成与使用
    •  模块化思想的运用

     相关链接:http://www.imgeek.org/article/825308542​ 
     
    Baby-开源私密社交应用
     
    推荐理由:私密社交APP,情侣、死党必备的一对一专属聊天应用。作者开发初期下载了市面上所有IM的demo源码跑一遍,从功能、集成难易和消息稳定几个方面对比,最终还是选择了环信。使用环信EaseUi集成,基本上一天就能集成完毕。

    baby.png

    项目运行效果图


    实现功能:
    • 加入Tinker 热修复
    • 加入部分注释
    • 增加长按删除功能
    • 优化Rxbus订阅加载数据
    • 外国友人优化的一些细节
    • 增加了评论功能
    • 优化了相册加载
    • 把登陆注册事件换了个Zip操作符更符合流的思想

    相关链接:http://www.imgeek.org/article/825308850

    LITE-IM-环信webim的网页即时聊天

    推荐理由:你见过最酷炫的WEB聊天项目,LITE-IM不仅能够担当客户服务来使用,还可以用作你网站粘连客户、活跃社区的媒介,提升用户的使用率。

    lym.png

    项目运行效果图


    [b]实现功能:[/b]
    • 好友/群内的文字、表情、图片、文件 在线/离线消息发送和接收。
    • 查看群员列表。 
    • 面板内快速查找。 
    • 面板右键自定义事件 
    • 修改签名 
    • 自定义上传背景皮肤 
    • 搜索好友/群 
    • 添加好友/群 
    • 新建群 
    • 消息盒子展示

     相关链接:http://www.imgeek.org/article/825308961 
     
    VMTVCall-使用环信3.xSDK 在 TV 端集成音视频通话功能
     
    推荐理由:移动互联网方便了我们生活,移动端随时随地沟通成为了常态,今天我们推荐的是一个可以安装在电视机上进行视频通话的开源项目。

    电视机.jpg

    项目运行效果图


     
    实现功能
    • 项目首次启动自动注册登录
    • 拨号盘实现
    • 历史通话记录 TODO
    • 视频通话功能(因为电视不需要语音通话以及最小化)
    • 视频通话的录制
    • 通话截图

     相关链接:http://www.imgeek.org/article/825308732
     
    end.
     
    生有涯而知无涯,业有涯而心无涯,路漫漫其修远,当上下而求索。未来,我们还将开源更多。
     
    环信IMGeek社区开源项目地址http://www.imgeek.org/code/
     
    9
    评论

    【新手快速入门】集成环信常见问题+解决方案汇总 常见问题

    dujiepeng 发表了文章 • 9754 次浏览 • 2017-05-22 15:51 • 来自相关话题

       这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
     
    ios篇
    APNs证书创建和上传到环信后台头像昵称的简述和处理方案音视频离线推送Demo实现环信服务器聊天记录保存多久?离线收不到好友请求IOS中环信聊天窗口如何实现文件发送和预览的功能ios集成常见问题环信推送的一些常见问题实现名片|红包|话题聊天室等自定义cell
     
    Android篇
    Android sdk 的两种导入方式环信3.0SDK集成小米推送教程EaseUI库中V4、v7包冲突解决方案Android EaseUI里的百度地图替换为高德地图android扩展消息(名片集成)关于会话列表的置顶聊天java.lang.UnsatisfiedLinkError: 的问题android 端 app 后台被杀死收不到消息的解决方案
    昵称头像篇
    android中如何显示开发者服务器上的昵称和头像 Android中显示头像(接上一篇文章看)环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)IOS中如何显示开发者服务器上的昵称和头像【环信公开课第12期视频回放】-所有关于环信IM昵称头像的问题听这课就够了
     
    直播篇
    一言不合你就搞个直播APP
     
    客服集成
    IM-SDK和客服SDK并存开发指南—Android篇IM-SDK和客服SDK并存开发指南—iOS篇
     
    开源项目
    Android简版demoios简版demo凡信2.0:超仿微信的开源项目 凡信3.0:携直播和红包而来高仿微信:Github 3,515 Star方圆十里:环信编程大赛冠军项目泛聊:定一个小目标写一个QQSlack聊天机器人:一天时间做一个聊天机器人TV视频通话:在电视上视频通话视频通话:Android手机视频通话酷信:ios高仿微信公众号助手:与订阅用户聊天沟通
     
    持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
      查看全部
       这里整理了集成环信的常见问题和一些功能的实现思路,希望能帮助到大家。感谢热心的开发者贡献,大家在观看过程中有不明白的地方欢迎直接跟帖咨询。
     
    ios篇

     
    Android篇

    昵称头像篇

     
    直播篇
    1. 一言不合你就搞个直播APP

     
    客服集成
    1. IM-SDK和客服SDK并存开发指南—Android篇
    2. IM-SDK和客服SDK并存开发指南—iOS篇

     
    开源项目

     
    持续更新ing...小伙伴们还有什么想知道欢迎跟帖提出。
     
    0
    回复

    加载EaseUI封装的聊天页面的添加id找不到 Android 环信

    回复

    gorky_19 发起了问题 • 1 人关注 • 117 次浏览 • 2018-02-08 14:46 • 来自相关话题

    0
    回复

    java.lang.IllegalArgumentException: No view found for id 0x7f07003a for fragment EaseChatFragment Android 环信

    回复

    gorky_19 发起了问题 • 1 人关注 • 117 次浏览 • 2018-02-08 11:27 • 来自相关话题

    2
    最佳

    看视频如果出现问题可以看这里 dyld: Library not loaded: @rpath/Hyphenate.framework/Hyphenate iOS 环信

    Rickie_Lambert 回复了问题 • 3 人关注 • 3430 次浏览 • 2017-11-27 15:51 • 来自相关话题

    7
    回复

    【环信官方外包一个项目】利用环信IM实现一个在线白板 环信

    g711ab 回复了问题 • 8 人关注 • 2035 次浏览 • 2017-11-23 15:52 • 来自相关话题

    1
    回复

    .a文件没找到 iOS 环信

    dujiepeng 回复了问题 • 2 人关注 • 295 次浏览 • 2017-11-06 18:24 • 来自相关话题

    0
    回复

    环信即时通讯 Unity,为什么只有用户的name,没有对应的id呢 环信

    回复

    叶孤城的橙 发起了问题 • 1 人关注 • 314 次浏览 • 2017-10-24 12:11 • 来自相关话题

    3
    回复

    环信离线推送消息自定义 离线 推送 环信 通知

    ╰☆╮末↘ 回复了问题 • 2 人关注 • 755 次浏览 • 2017-09-14 11:42 • 来自相关话题

    0
    评论

    【环信征文】集成环信,并实现消息免打扰 即时通讯 环信 消息免打扰 IM iOS

    cokeyer 发表了文章 • 281 次浏览 • 2017-09-14 11:27 • 来自相关话题

    现在大多数社交app都有消息免打扰功能,因为环信SDK主要是对即时通讯模块进行封装,因此如果要实现消息免打扰功能则需要开发者自己对此功能逻辑进行处理。
    先解释一下,本人项目中对消息免打扰功能的定义:正常情况下,我们收到的每一条聊天消息都会收到小红点、声音、震动的提示。如果对某个好友设置消息免打扰功能,则只提示小红点,声音和震动则不再提示。

    下面简述结合环信SDK时,此功能的实现方法。
    环信将即时聊天的所有功能分为四大模块进行管理://聊天模块:
    [EMClient sharedClient].chatManager
    //好友模块 :
    [EMClient sharedClient].contactManager
    //群组模块 :
    [EMClient sharedClient].groupManager
    //聊天室模块:
    [EMClient sharedClient].roomManager消息免打扰的功能借助聊天模块[EMClient sharedClient].chatManager的API就能实现。
    一般来说,在app内不管当前在哪个界面,只要收到消息都需要被判断是否需要免打扰,因此可以在appdelegate里写如下代码,app通常都有tabBarController,那么也可以让tabBarController来实现如下代码。
    首先让控制器tabBarController遵守代理EMChatManagerDelegate
    然后成为代理
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

    EMChatManagerDelegate中有一个代理方法- (void)didReceiveMessages:(NSArray *)aMessages;实现此代理方法- (void)didReceiveMessages:(NSArray *)aMessages{
    [self setupUnreadMessageCount];
    EMMessage *message = aMessages[0];
    NSString *sendPerson = message.from;
    BHNavigatiomController *imNaviCV = self.viewControllers[1];
    BHConversationListController *converCV = imNaviCV.viewControllers[0];
    [converCV refreshDataSource];//只要收到消息就从服务器拿
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    for (NSString *hx_name in AppEngine.IMDataCent.data_ExcuseFriendsData) {
    if ([hx_name isEqualToString:sendPerson]) {
    return;
    }
    }
    switch (state) {
    case UIApplicationStateActive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateInactive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateBackground:
    [self showNotificationWithMessage:message];
    break;
    default:
    break;
    }
    }方法中有一个aMessages参数。这个参数是一个消息组,每一个元素都是EMMessage类型的实例。
    因为通常都只有一条信息。因此只需要取出EMMessage *message = aMessages[0];
    EMMessage类中有许多属性,因此根据一条信息基本可以获取想知道的所有信息。这里我们只需要知道此消息的发送方即可,也就是发送方的环信idNSString *sendPerson = message.from;下面代码中有一AppEngine.IMDataCent.data_ExcuseFriendsData,这个数组里面装的都是已经被设置消息免打扰的好友的环信id,是请求自己服务器获得的,获取的代码最好在一打开app时,就及时获取到。然后根据对好友免打扰设置的操作,访问后台接口进行增删,并刷新数组与后端保持一致即可。
    通过[hx_name isEqualToString:sendPerson],遍历免打扰数组与当前消息的发送方环信id,就可以知道是否需要免打扰了。
     
    下面附上完整代码//
    // BHTabBarController.m
    // ShangHeYiYang
    //
    // Created by LiBohan on 2017/8/24.
    // Copyright © 2017年 xxxxx. All rights reserved.
    //


    //两次提示的默认间隔
    static const CGFloat kDefaultPlaySoundInterval = 3.0;
    static NSString *kMessageType = @"MessageType";
    static NSString *kConversationChatter = @"ConversationChatter";
    static NSString *kGroupName = @"GroupName";


    #import "BHTabBarController.h"
    #import <UserNotifications/UserNotifications.h>
    #import "BHConversationListController.h"

    @interface BHTabBarController ()<EMChatManagerDelegate,EMContactManagerDelegate>

    @property (strong, nonatomic) NSDate *lastPlaySoundDate;

    @end

    @implementation BHTabBarController

    - (void)viewDidLoad {
    [super viewDidLoad];

    [DemoCallManager sharedManager].mainController = self;

    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

    [[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupUnreadMessageCount) name:@"setupUnreadMessageCount" object:nil];

    }

    -(void)friendshipDidRemoveByUser:(NSString *)aUsername{

    // __weak __typeof(&*self)weakSelf = self;

    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0/*延迟执行时间*/ * NSEC_PER_SEC));

    dispatch_after(delay, dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:contactReloadData object:nil];
    });


    // if ([AppEngine.mainDataCent.data_UserData.data_HxID isEqualToString:aUsername]) {


    //删除好友成功后,再删除聊天会话
    [[EMClient sharedClient].chatManager deleteConversation:aUsername isDeleteMessages:YES completion:^(NSString *aConversationId, EMError *aError) {

    if (!aError) {
    //删除聊天会话,成功后,刷新聊天会话列表
    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0/*延迟执行时间*/ * NSEC_PER_SEC));

    dispatch_after(delay, dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:talkBtnClickThenUpdateConversionlist object:nil];
    });


    }

    }];
    }

    // 统计未读消息数
    -(void)setupUnreadMessageCount
    {
    NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
    NSInteger unreadCount = 0;
    for (EMConversation *conversation in conversations) {
    unreadCount += conversation.unreadMessagesCount;
    }

    NSArray *tabBarItems = self.tabBar.items;

    UITabBarItem *conlistTabBarItem = [tabBarItems objectAtIndex:1];
    if (unreadCount > 0) {
    conlistTabBarItem.badgeValue = [NSString stringWithFormat:@"%i",(int)unreadCount];
    }else{
    conlistTabBarItem.badgeValue = nil;
    }


    // UIApplication *application = [UIApplication sharedApplication];
    // [application setApplicationIconBadgeNumber:unreadCount];
    }


    - (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages {
    for (EMMessage *message in aCmdMessages) {
    EMCmdMessageBody *body = (EMCmdMessageBody *)message.body;
    NSLog(@"收到的action是 -- %@",body.action);


    if (body.action == nil) {

    return;

    }

    NSData *jsonData = [body.action dataUsingEncoding:NSUTF8StringEncoding];

    NSError *err;

    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];

    if(err) {

    NSLog(@"json解析失败:%@",err);

    return;

    }

    NSNumber *num = dic[@"count"];

    NSString *str = [num stringValue];

    [AppEngine.IMDataCent requestUpdateUnreadNumberWithUnreadNumber:str];

    }


    }

    - (void)didReceiveMessages:(NSArray *)aMessages{

    // [self refresh];

    [self setupUnreadMessageCount];

    EMMessage *message = aMessages[0];

    NSString *sendPerson = message.from;

    BHNavigatiomController *imNaviCV = self.viewControllers[1];

    BHConversationListController *converCV = imNaviCV.viewControllers[0];

    // [converCV refresh];

    [converCV refreshDataSource];//只要收到消息就从服务器拿

    UIApplicationState state = [[UIApplication sharedApplication] applicationState];

    for (NSString *hx_name in AppEngine.IMDataCent.data_ExcuseFriendsData) {

    if ([hx_name isEqualToString:sendPerson]) {
    return;
    }

    }

    switch (state) {
    case UIApplicationStateActive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateInactive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateBackground:
    [self showNotificationWithMessage:message];
    break;
    default:
    break;
    }

    }

    - (void)playSoundAndVibration{
    NSTimeInterval timeInterval = [[NSDate date]
    timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval) {
    //如果距离上次响铃和震动时间太短, 则跳过响铃
    NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
    return;
    }

    //保存最后一次响铃时间
    self.lastPlaySoundDate = [NSDate date];

    // 收到消息时,播放音频
    [[EMCDDeviceManager sharedInstance] playNewMessageSound];
    // 收到消息时,震动
    [[EMCDDeviceManager sharedInstance] playVibration];
    }


    - (void)showNotificationWithMessage:(EMMessage *)message
    {
    EMPushOptions *options = [[EMClient sharedClient] pushOptions];
    NSString *alertBody = nil;
    if (options.displayStyle == EMPushDisplayStyleMessageSummary) {
    EMMessageBody *messageBody = message.body;
    NSString *messageStr = nil;
    switch (messageBody.type) {
    case EMMessageBodyTypeText:
    {
    messageStr = ((EMTextMessageBody *)messageBody).text;
    }
    break;
    case EMMessageBodyTypeImage:
    {
    messageStr = NSLocalizedString(@"message.image", @"Image");
    }
    break;
    case EMMessageBodyTypeLocation:
    {
    messageStr = NSLocalizedString(@"message.location", @"Location");
    }
    break;
    case EMMessageBodyTypeVoice:
    {
    messageStr = NSLocalizedString(@"message.voice", @"Voice");
    }
    break;
    case EMMessageBodyTypeVideo:{
    messageStr = NSLocalizedString(@"message.video", @"Video");
    }
    break;
    default:
    break;
    }

    do {
    // NSString *title = [[UserProfileManager sharedInstance] getNickNameWithUsername:message.from];
    NSString *title = @"大佬";

    if (message.chatType == EMChatTypeGroupChat) {
    NSDictionary *ext = message.ext;
    if (ext && ext[kGroupMessageAtList]) {
    id target = ext[kGroupMessageAtList];
    if ([target isKindOfClass:[NSString class]]) {
    if ([kGroupMessageAtAll compare:target options:NSCaseInsensitiveSearch] == NSOrderedSame) {
    alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
    break;
    }
    }
    else if ([target isKindOfClass:[NSArray class]]) {
    NSArray *atTargets = (NSArray*)target;
    if ([atTargets containsObject:[EMClient sharedClient].currentUsername]) {
    alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
    break;
    }
    }
    }
    NSArray *groupArray = [[EMClient sharedClient].groupManager getJoinedGroups];
    for (EMGroup *group in groupArray) {
    if ([group.groupId isEqualToString:message.conversationId]) {
    title = [NSString stringWithFormat:@"%@(%@)", message.from, group.subject];
    break;
    }
    }
    }
    else if (message.chatType == EMChatTypeChatRoom)
    {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    NSString *key = [NSString stringWithFormat:@"OnceJoinedChatrooms_%@", [[EMClient sharedClient] currentUsername]];
    NSMutableDictionary *chatrooms = [NSMutableDictionary dictionaryWithDictionary:[ud objectForKey:key]];
    NSString *chatroomName = [chatrooms objectForKey:message.conversationId];
    if (chatroomName)
    {
    title = [NSString stringWithFormat:@"%@(%@)", message.from, chatroomName];
    }
    }

    alertBody = [NSString stringWithFormat:@"%@:%@", title, messageStr];
    } while (0);
    }
    else{
    // alertBody = NSLocalizedString(@"receiveMessage", @"you have a new message");
    alertBody = @"您有一条消息";
    }

    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    BOOL playSound = NO;
    if (!self.lastPlaySoundDate || timeInterval >= kDefaultPlaySoundInterval) {
    self.lastPlaySoundDate = [NSDate date];
    playSound = YES;
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:message.chatType] forKey:kMessageType];
    [userInfo setObject:message.conversationId forKey:kConversationChatter];

    //发送本地推送
    if (NSClassFromString(@"UNUserNotificationCenter")) {
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    if (playSound) {
    content.sound = [UNNotificationSound defaultSound];
    }
    content.body =alertBody;
    content.userInfo = userInfo;
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.messageId content:content trigger:trigger];
    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
    }
    else {
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.fireDate = [NSDate date]; //触发通知的时间
    notification.alertBody = alertBody;
    notification.alertAction = NSLocalizedString(@"open", @"Open");
    notification.timeZone = [NSTimeZone defaultTimeZone];
    if (playSound) {
    notification.soundName = UILocalNotificationDefaultSoundName;
    }
    notification.userInfo = userInfo;

    //发送通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    }
    }

    - (void)messagesDidDeliver:(NSArray *)aMessages{

    NSLog(@"sf");
    }


    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    /*
    #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    }
    */

    @end


     
     
    本人github:https://github.com/BHAreslee
    本人简书:http://www.jianshu.com/u/bb53043aaa00
    以上就是集成环信时暂时发现的问题,欢迎大家分享你们遇到的问题,也欢迎加入QQ群:372251359,一起讨论交流即时通讯的问题。
    本人微信公众号:放心安慰剂 查看全部
    现在大多数社交app都有消息免打扰功能,因为环信SDK主要是对即时通讯模块进行封装,因此如果要实现消息免打扰功能则需要开发者自己对此功能逻辑进行处理。
    先解释一下,本人项目中对消息免打扰功能的定义:正常情况下,我们收到的每一条聊天消息都会收到小红点、声音、震动的提示。如果对某个好友设置消息免打扰功能,则只提示小红点,声音和震动则不再提示。

    下面简述结合环信SDK时,此功能的实现方法。
    环信将即时聊天的所有功能分为四大模块进行管理:
    //聊天模块:
    [EMClient sharedClient].chatManager
    //好友模块 :
    [EMClient sharedClient].contactManager
    //群组模块 :
    [EMClient sharedClient].groupManager
    //聊天室模块:
    [EMClient sharedClient].roomManager
    消息免打扰的功能借助聊天模块[EMClient sharedClient].chatManager的API就能实现。
    一般来说,在app内不管当前在哪个界面,只要收到消息都需要被判断是否需要免打扰,因此可以在appdelegate里写如下代码,app通常都有tabBarController,那么也可以让tabBarController来实现如下代码。
    首先让控制器tabBarController遵守代理EMChatManagerDelegate
    然后成为代理
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

    EMChatManagerDelegate中有一个代理方法
    - (void)didReceiveMessages:(NSArray *)aMessages;
    实现此代理方法
    - (void)didReceiveMessages:(NSArray *)aMessages{
    [self setupUnreadMessageCount];
    EMMessage *message = aMessages[0];
    NSString *sendPerson = message.from;
    BHNavigatiomController *imNaviCV = self.viewControllers[1];
    BHConversationListController *converCV = imNaviCV.viewControllers[0];
    [converCV refreshDataSource];//只要收到消息就从服务器拿
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    for (NSString *hx_name in AppEngine.IMDataCent.data_ExcuseFriendsData) {
    if ([hx_name isEqualToString:sendPerson]) {
    return;
    }
    }
    switch (state) {
    case UIApplicationStateActive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateInactive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateBackground:
    [self showNotificationWithMessage:message];
    break;
    default:
    break;
    }
    }
    方法中有一个aMessages参数。这个参数是一个消息组,每一个元素都是EMMessage类型的实例。
    因为通常都只有一条信息。因此只需要取出EMMessage *message = aMessages[0];
    EMMessage类中有许多属性,因此根据一条信息基本可以获取想知道的所有信息。这里我们只需要知道此消息的发送方即可,也就是发送方的环信idNSString *sendPerson = message.from;下面代码中有一AppEngine.IMDataCent.data_ExcuseFriendsData,这个数组里面装的都是已经被设置消息免打扰的好友的环信id,是请求自己服务器获得的,获取的代码最好在一打开app时,就及时获取到。然后根据对好友免打扰设置的操作,访问后台接口进行增删,并刷新数组与后端保持一致即可。
    通过[hx_name isEqualToString:sendPerson],遍历免打扰数组与当前消息的发送方环信id,就可以知道是否需要免打扰了。
     
    下面附上完整代码
    //
    // BHTabBarController.m
    // ShangHeYiYang
    //
    // Created by LiBohan on 2017/8/24.
    // Copyright © 2017年 xxxxx. All rights reserved.
    //


    //两次提示的默认间隔
    static const CGFloat kDefaultPlaySoundInterval = 3.0;
    static NSString *kMessageType = @"MessageType";
    static NSString *kConversationChatter = @"ConversationChatter";
    static NSString *kGroupName = @"GroupName";


    #import "BHTabBarController.h"
    #import <UserNotifications/UserNotifications.h>
    #import "BHConversationListController.h"

    @interface BHTabBarController ()<EMChatManagerDelegate,EMContactManagerDelegate>

    @property (strong, nonatomic) NSDate *lastPlaySoundDate;

    @end

    @implementation BHTabBarController

    - (void)viewDidLoad {
    [super viewDidLoad];

    [DemoCallManager sharedManager].mainController = self;

    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

    [[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupUnreadMessageCount) name:@"setupUnreadMessageCount" object:nil];

    }

    -(void)friendshipDidRemoveByUser:(NSString *)aUsername{

    // __weak __typeof(&*self)weakSelf = self;

    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0/*延迟执行时间*/ * NSEC_PER_SEC));

    dispatch_after(delay, dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:contactReloadData object:nil];
    });


    // if ([AppEngine.mainDataCent.data_UserData.data_HxID isEqualToString:aUsername]) {


    //删除好友成功后,再删除聊天会话
    [[EMClient sharedClient].chatManager deleteConversation:aUsername isDeleteMessages:YES completion:^(NSString *aConversationId, EMError *aError) {

    if (!aError) {
    //删除聊天会话,成功后,刷新聊天会话列表
    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0/*延迟执行时间*/ * NSEC_PER_SEC));

    dispatch_after(delay, dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:talkBtnClickThenUpdateConversionlist object:nil];
    });


    }

    }];
    }

    // 统计未读消息数
    -(void)setupUnreadMessageCount
    {
    NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
    NSInteger unreadCount = 0;
    for (EMConversation *conversation in conversations) {
    unreadCount += conversation.unreadMessagesCount;
    }

    NSArray *tabBarItems = self.tabBar.items;

    UITabBarItem *conlistTabBarItem = [tabBarItems objectAtIndex:1];
    if (unreadCount > 0) {
    conlistTabBarItem.badgeValue = [NSString stringWithFormat:@"%i",(int)unreadCount];
    }else{
    conlistTabBarItem.badgeValue = nil;
    }


    // UIApplication *application = [UIApplication sharedApplication];
    // [application setApplicationIconBadgeNumber:unreadCount];
    }


    - (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages {
    for (EMMessage *message in aCmdMessages) {
    EMCmdMessageBody *body = (EMCmdMessageBody *)message.body;
    NSLog(@"收到的action是 -- %@",body.action);


    if (body.action == nil) {

    return;

    }

    NSData *jsonData = [body.action dataUsingEncoding:NSUTF8StringEncoding];

    NSError *err;

    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];

    if(err) {

    NSLog(@"json解析失败:%@",err);

    return;

    }

    NSNumber *num = dic[@"count"];

    NSString *str = [num stringValue];

    [AppEngine.IMDataCent requestUpdateUnreadNumberWithUnreadNumber:str];

    }


    }

    - (void)didReceiveMessages:(NSArray *)aMessages{

    // [self refresh];

    [self setupUnreadMessageCount];

    EMMessage *message = aMessages[0];

    NSString *sendPerson = message.from;

    BHNavigatiomController *imNaviCV = self.viewControllers[1];

    BHConversationListController *converCV = imNaviCV.viewControllers[0];

    // [converCV refresh];

    [converCV refreshDataSource];//只要收到消息就从服务器拿

    UIApplicationState state = [[UIApplication sharedApplication] applicationState];

    for (NSString *hx_name in AppEngine.IMDataCent.data_ExcuseFriendsData) {

    if ([hx_name isEqualToString:sendPerson]) {
    return;
    }

    }

    switch (state) {
    case UIApplicationStateActive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateInactive:
    [self playSoundAndVibration];
    break;
    case UIApplicationStateBackground:
    [self showNotificationWithMessage:message];
    break;
    default:
    break;
    }

    }

    - (void)playSoundAndVibration{
    NSTimeInterval timeInterval = [[NSDate date]
    timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval) {
    //如果距离上次响铃和震动时间太短, 则跳过响铃
    NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
    return;
    }

    //保存最后一次响铃时间
    self.lastPlaySoundDate = [NSDate date];

    // 收到消息时,播放音频
    [[EMCDDeviceManager sharedInstance] playNewMessageSound];
    // 收到消息时,震动
    [[EMCDDeviceManager sharedInstance] playVibration];
    }


    - (void)showNotificationWithMessage:(EMMessage *)message
    {
    EMPushOptions *options = [[EMClient sharedClient] pushOptions];
    NSString *alertBody = nil;
    if (options.displayStyle == EMPushDisplayStyleMessageSummary) {
    EMMessageBody *messageBody = message.body;
    NSString *messageStr = nil;
    switch (messageBody.type) {
    case EMMessageBodyTypeText:
    {
    messageStr = ((EMTextMessageBody *)messageBody).text;
    }
    break;
    case EMMessageBodyTypeImage:
    {
    messageStr = NSLocalizedString(@"message.image", @"Image");
    }
    break;
    case EMMessageBodyTypeLocation:
    {
    messageStr = NSLocalizedString(@"message.location", @"Location");
    }
    break;
    case EMMessageBodyTypeVoice:
    {
    messageStr = NSLocalizedString(@"message.voice", @"Voice");
    }
    break;
    case EMMessageBodyTypeVideo:{
    messageStr = NSLocalizedString(@"message.video", @"Video");
    }
    break;
    default:
    break;
    }

    do {
    // NSString *title = [[UserProfileManager sharedInstance] getNickNameWithUsername:message.from];
    NSString *title = @"大佬";

    if (message.chatType == EMChatTypeGroupChat) {
    NSDictionary *ext = message.ext;
    if (ext && ext[kGroupMessageAtList]) {
    id target = ext[kGroupMessageAtList];
    if ([target isKindOfClass:[NSString class]]) {
    if ([kGroupMessageAtAll compare:target options:NSCaseInsensitiveSearch] == NSOrderedSame) {
    alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
    break;
    }
    }
    else if ([target isKindOfClass:[NSArray class]]) {
    NSArray *atTargets = (NSArray*)target;
    if ([atTargets containsObject:[EMClient sharedClient].currentUsername]) {
    alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
    break;
    }
    }
    }
    NSArray *groupArray = [[EMClient sharedClient].groupManager getJoinedGroups];
    for (EMGroup *group in groupArray) {
    if ([group.groupId isEqualToString:message.conversationId]) {
    title = [NSString stringWithFormat:@"%@(%@)", message.from, group.subject];
    break;
    }
    }
    }
    else if (message.chatType == EMChatTypeChatRoom)
    {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    NSString *key = [NSString stringWithFormat:@"OnceJoinedChatrooms_%@", [[EMClient sharedClient] currentUsername]];
    NSMutableDictionary *chatrooms = [NSMutableDictionary dictionaryWithDictionary:[ud objectForKey:key]];
    NSString *chatroomName = [chatrooms objectForKey:message.conversationId];
    if (chatroomName)
    {
    title = [NSString stringWithFormat:@"%@(%@)", message.from, chatroomName];
    }
    }

    alertBody = [NSString stringWithFormat:@"%@:%@", title, messageStr];
    } while (0);
    }
    else{
    // alertBody = NSLocalizedString(@"receiveMessage", @"you have a new message");
    alertBody = @"您有一条消息";
    }

    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    BOOL playSound = NO;
    if (!self.lastPlaySoundDate || timeInterval >= kDefaultPlaySoundInterval) {
    self.lastPlaySoundDate = [NSDate date];
    playSound = YES;
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:message.chatType] forKey:kMessageType];
    [userInfo setObject:message.conversationId forKey:kConversationChatter];

    //发送本地推送
    if (NSClassFromString(@"UNUserNotificationCenter")) {
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    if (playSound) {
    content.sound = [UNNotificationSound defaultSound];
    }
    content.body =alertBody;
    content.userInfo = userInfo;
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.messageId content:content trigger:trigger];
    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
    }
    else {
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.fireDate = [NSDate date]; //触发通知的时间
    notification.alertBody = alertBody;
    notification.alertAction = NSLocalizedString(@"open", @"Open");
    notification.timeZone = [NSTimeZone defaultTimeZone];
    if (playSound) {
    notification.soundName = UILocalNotificationDefaultSoundName;
    }
    notification.userInfo = userInfo;

    //发送通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    }
    }

    - (void)messagesDidDeliver:(NSArray *)aMessages{

    NSLog(@"sf");
    }


    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    /*
    #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    }
    */

    @end


     
     
    本人github:https://github.com/BHAreslee
    本人简书:http://www.jianshu.com/u/bb53043aaa00
    以上就是集成环信时暂时发现的问题,欢迎大家分享你们遇到的问题,也欢迎加入QQ群:372251359,一起讨论交流即时通讯的问题。
    本人微信公众号:放心安慰剂

    qrcode_for_gh_bc92a063b4a2_430.jpg
    0
    评论

    【环信征文】基于环信开发一个医疗APP-Ⅰ iOS 环信 即时通讯 IM

    cokeyer 发表了文章 • 276 次浏览 • 2017-09-12 17:56 • 来自相关话题

    公司又有了新项目,依然是含有即时通讯功能模块的项目。在经历了上个项目对环信sdk的集成后,对环信EaseUI有了大概的了解。这次果断还是集成环信,一回生二回熟,最主要的还是对环信IM稳定性非常放心!项目医疗类的项目,角色分医生和患者,双方都可主动发起会话,但如果是患者找医生聊天,必须先经过预约,并只能在预约时间区间内才能和医生发送聊天消息、图片、语音、实时音视频。项目基于环信最V3.3.4版本开发,首先在会话界面自定义一个类比如BHChatViewController,继承自EaseMessageViewController类,基本上一个简单的界面就有了。以下就是EaseMessageViewController类的发送各种消息的方法,那么根据需要只需重写以下方法即可。/*!
    @method
    @brief 发送文本消息
    @discussion
    @param text 文本消息
    @result
    */
    - (void)sendTextMessage:(NSString *)text;

    /*!
    @method
    @brief 发送文本消息
    @discussion
    @param text 文本消息
    @param ext 扩展信息
    @result
    */
    - (void)sendTextMessage:(NSString *)text withExt:(NSDictionary*)ext;

    /*!
    @method
    @brief 发送图片消息
    @discussion
    @param image 发送图片
    @result
    */
    - (void)sendImageMessage:(UIImage *)image;

    /*!
    @method
    @brief 发送位置消息
    @discussion
    @param latitude 经度
    @param longitude 纬度
    @param address 地址
    @result
    */
    - (void)sendLocationMessageLatitude:(double)latitude
    longitude:(double)longitude
    andAddress:(NSString *)address;

    /*!
    @method
    @brief 发送语音消息
    @discussion
    @param localPath 语音本地地址
    @param duration 时长
    @result
    */
    - (void)sendVoiceMessageWithLocalPath:(NSString *)localPath
    duration:(NSInteger)duration;

    /*!
    @method
    @brief 发送视频消息
    @discussion
    @param url 视频url
    @result
    */
    - (void)sendVideoMessageWithURL:(NSURL *)url;我在对发送图片的操作进行处理的时候,发现当拍照发图时,走这个方法//当你拍照发图时,走这个方法
    - (void)sendImageMessage:(UIImage *)image;但当从相册选择图片发送时,会发现,不走上面的方法了。
    仔细检查代码发现走了EaseMessageViewController.m的如下方法





    然而这个方法,环信并没有放在EaseMessageViewController.h成为公开方法。我们只需手动粘贴方法到.h,然后在自己的子类重写就可以了。

    还有一个关于更多下图更多功能区域的问题





    如上图所示,相册、拍照、视频等附加功能按钮,环信用EaseChatBarMoreView类来管理的。
    如果需要增加功能按钮用这个方法/*!
    @method
    @brief 新增一个新的功能按钮
    @discussion
    @param image 按钮图片
    @param highLightedImage 高亮图片
    @param title 按钮标题
    @result
    */
    - (void)insertItemWithImage:(UIImage*)image
    highlightedImage:(UIImage*)highLightedImage
    title:(NSString*)title;移除某个功能按钮用这个方法/*!
    @method
    @brief 根据索引删除功能按钮
    @discussion
    @param index 按钮索引
    @result
    */
    - (void)removeItematIndex:(NSInteger)index;修改一个功能按钮用这个方法/*!
    @method
    @brief 修改功能按钮图片
    @discussion
    @param image 按钮图片
    @param highLightedImage 高亮图片
    @param title 按钮标题
    @param index 按钮索引
    @result
    */
    - (void)updateItemWithImage:(UIImage*)image
    highlightedImage:(UIImage*)highLightedImage
    title:(NSString*)title
    atIndex:(NSInteger)index;可当你添加按钮,或者修改按钮时,会发现按钮的名字设置不了
    然后检查环信内部的实现,发现title的值在方法里根本就没用到?!
    索性不用updateItemWithImage这个方法了,直接去改内部代码。
    修改代码如下

    到EaseChatBarMoreView.m修改- (void)setupSubviewsForType:(EMChatToolbarType)type方法。改动的部分在代码后面有标注。- (void)setupSubviewsForType:(EMChatToolbarType)type
    {
    //self.backgroundColor = [UIColor clearColor];
    self.accessibilityIdentifier = @"more_view";

    _scrollview = [[UIScrollView alloc] init];
    _scrollview.pagingEnabled = YES;
    _scrollview.showsHorizontalScrollIndicator = NO;
    _scrollview.showsVerticalScrollIndicator = NO;
    _scrollview.delegate = self;
    [self addSubview:_scrollview];

    _pageControl = [[UIPageControl alloc] init];
    _pageControl.currentPage = 0;
    _pageControl.numberOfPages = 1;
    [self addSubview:_pageControl];

    CGFloat insets = (self.frame.size.width - 4 * CHAT_BUTTON_SIZE) / 5;

    _photoButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_photoButton setTitle:@"相册" forState:UIControlStateNormal];//改动
    [_photoButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _photoButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _photoButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _photoButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    _photoButton.accessibilityIdentifier = @"image";
    [_photoButton setFrame:CGRectMake(insets, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//改动
    [_photoButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_photo"] forState:UIControlStateNormal];
    [_photoButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_photoSelected"] forState:UIControlStateHighlighted];
    [_photoButton addTarget:self action:@selector(photoAction) forControlEvents:UIControlEventTouchUpInside];
    _photoButton.tag = MOREVIEW_BUTTON_TAG;
    [_scrollview addSubview:_photoButton];

    _locationButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_locationButton setTitle:@"位置" forState:UIControlStateNormal];//改动
    [_locationButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _locationButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _locationButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _locationButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    _locationButton.accessibilityIdentifier = @"location";
    [_locationButton setFrame:CGRectMake(insets * 2 + CHAT_BUTTON_SIZE, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_locationButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_location"] forState:UIControlStateNormal];
    [_locationButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_locationSelected"] forState:UIControlStateHighlighted];
    [_locationButton addTarget:self action:@selector(locationAction) forControlEvents:UIControlEventTouchUpInside];
    _locationButton.tag = MOREVIEW_BUTTON_TAG + 1;
    [_scrollview addSubview:_locationButton];

    _takePicButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_takePicButton setTitle:@"拍照" forState:UIControlStateNormal];//改动
    [_takePicButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _takePicButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _takePicButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _takePicButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_takePicButton setFrame:CGRectMake(insets * 3 + CHAT_BUTTON_SIZE * 2, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//改动
    [_takePicButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_camera"] forState:UIControlStateNormal];
    [_takePicButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_cameraSelected"] forState:UIControlStateHighlighted];
    [_takePicButton addTarget:self action:@selector(takePicAction) forControlEvents:UIControlEventTouchUpInside];
    _takePicButton.tag = MOREVIEW_BUTTON_TAG + 2;
    _maxIndex = 2;
    [_scrollview addSubview:_takePicButton];

    CGRect frame = self.frame;
    if (type == EMChatToolbarTypeChat) {
    frame.size.height = 150;
    _audioCallButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_audioCallButton setTitle:@"语音" forState:UIControlStateNormal];//改动
    [_audioCallButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _audioCallButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _audioCallButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _audioCallButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_audioCallButton setFrame:CGRectMake(insets * 4 + CHAT_BUTTON_SIZE * 3, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_audioCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_audioCall"] forState:UIControlStateNormal];
    [_audioCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_audioCallSelected"] forState:UIControlStateHighlighted];
    [_audioCallButton addTarget:self action:@selector(takeAudioCallAction) forControlEvents:UIControlEventTouchUpInside];
    _audioCallButton.tag = MOREVIEW_BUTTON_TAG + 3;
    [_scrollview addSubview:_audioCallButton];

    _videoCallButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_videoCallButton setTitle:@"视频" forState:UIControlStateNormal];//改动
    [_videoCallButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _videoCallButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _videoCallButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _videoCallButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_videoCallButton setFrame:CGRectMake(insets, 10 * 2 + CHAT_BUTTON_SIZE + 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_videoCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_videoCall"] forState:UIControlStateNormal];
    [_videoCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_videoCallSelected"] forState:UIControlStateHighlighted];
    [_videoCallButton addTarget:self action:@selector(takeVideoCallAction) forControlEvents:UIControlEventTouchUpInside];
    _videoCallButton.tag =MOREVIEW_BUTTON_TAG + 4;
    _maxIndex = 4;
    [_scrollview addSubview:_videoCallButton];
    }
    else if (type == EMChatToolbarTypeGroup)
    {
    frame.size.height = 80;
    }
    self.frame = frame;
    _scrollview.frame = CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
    _pageControl.frame = CGRectMake(0, CGRectGetHeight(frame) - 20, CGRectGetWidth(frame), 20);
    _pageControl.hidden = _pageControl.numberOfPages<=1;
    }




    本人github:https://github.com/BHAreslee
    本人简书:http://www.jianshu.com/u/bb53043aaa00
    以上就是集成环信时暂时发现的问题,欢迎大家分享你们遇到的问题,也欢迎加入QQ群:372251359,一起讨论交流即时通讯的问题。
    本人微信公众号:放心安慰剂





     
    项目完整源码 查看全部
    公司又有了新项目,依然是含有即时通讯功能模块的项目。在经历了上个项目对环信sdk的集成后,对环信EaseUI有了大概的了解。这次果断还是集成环信,一回生二回熟,最主要的还是对环信IM稳定性非常放心!
    项目医疗类的项目,角色分医生和患者,双方都可主动发起会话,但如果是患者找医生聊天,必须先经过预约,并只能在预约时间区间内才能和医生发送聊天消息、图片、语音、实时音视频。项目基于环信最V3.3.4版本开发,首先在会话界面自定义一个类比如BHChatViewController,继承自EaseMessageViewController类,基本上一个简单的界面就有了。以下就是EaseMessageViewController类的发送各种消息的方法,那么根据需要只需重写以下方法即可。
    /*!
    @method
    @brief 发送文本消息
    @discussion
    @param text 文本消息
    @result
    */
    - (void)sendTextMessage:(NSString *)text;

    /*!
    @method
    @brief 发送文本消息
    @discussion
    @param text 文本消息
    @param ext 扩展信息
    @result
    */
    - (void)sendTextMessage:(NSString *)text withExt:(NSDictionary*)ext;

    /*!
    @method
    @brief 发送图片消息
    @discussion
    @param image 发送图片
    @result
    */
    - (void)sendImageMessage:(UIImage *)image;

    /*!
    @method
    @brief 发送位置消息
    @discussion
    @param latitude 经度
    @param longitude 纬度
    @param address 地址
    @result
    */
    - (void)sendLocationMessageLatitude:(double)latitude
    longitude:(double)longitude
    andAddress:(NSString *)address;

    /*!
    @method
    @brief 发送语音消息
    @discussion
    @param localPath 语音本地地址
    @param duration 时长
    @result
    */
    - (void)sendVoiceMessageWithLocalPath:(NSString *)localPath
    duration:(NSInteger)duration;

    /*!
    @method
    @brief 发送视频消息
    @discussion
    @param url 视频url
    @result
    */
    - (void)sendVideoMessageWithURL:(NSURL *)url;
    我在对发送图片的操作进行处理的时候,发现当拍照发图时,走这个方法
    //当你拍照发图时,走这个方法
    - (void)sendImageMessage:(UIImage *)image;
    但当从相册选择图片发送时,会发现,不走上面的方法了。
    仔细检查代码发现走了EaseMessageViewController.m的如下方法

    环信2.png

    然而这个方法,环信并没有放在EaseMessageViewController.h成为公开方法。我们只需手动粘贴方法到.h,然后在自己的子类重写就可以了。

    还有一个关于更多下图更多功能区域的问题

    EaseChatBarMoreView.png

    如上图所示,相册、拍照、视频等附加功能按钮,环信用EaseChatBarMoreView类来管理的。
    如果需要增加功能按钮用这个方法
    /*!
    @method
    @brief 新增一个新的功能按钮
    @discussion
    @param image 按钮图片
    @param highLightedImage 高亮图片
    @param title 按钮标题
    @result
    */
    - (void)insertItemWithImage:(UIImage*)image
    highlightedImage:(UIImage*)highLightedImage
    title:(NSString*)title;
    移除某个功能按钮用这个方法
    /*!
    @method
    @brief 根据索引删除功能按钮
    @discussion
    @param index 按钮索引
    @result
    */
    - (void)removeItematIndex:(NSInteger)index;
    修改一个功能按钮用这个方法
    /*!
    @method
    @brief 修改功能按钮图片
    @discussion
    @param image 按钮图片
    @param highLightedImage 高亮图片
    @param title 按钮标题
    @param index 按钮索引
    @result
    */
    - (void)updateItemWithImage:(UIImage*)image
    highlightedImage:(UIImage*)highLightedImage
    title:(NSString*)title
    atIndex:(NSInteger)index;
    可当你添加按钮,或者修改按钮时,会发现按钮的名字设置不了
    然后检查环信内部的实现,发现title的值在方法里根本就没用到?!
    索性不用updateItemWithImage这个方法了,直接去改内部代码。
    修改代码如下

    到EaseChatBarMoreView.m修改- (void)setupSubviewsForType:(EMChatToolbarType)type方法。改动的部分在代码后面有标注。
    - (void)setupSubviewsForType:(EMChatToolbarType)type
    {
    //self.backgroundColor = [UIColor clearColor];
    self.accessibilityIdentifier = @"more_view";

    _scrollview = [[UIScrollView alloc] init];
    _scrollview.pagingEnabled = YES;
    _scrollview.showsHorizontalScrollIndicator = NO;
    _scrollview.showsVerticalScrollIndicator = NO;
    _scrollview.delegate = self;
    [self addSubview:_scrollview];

    _pageControl = [[UIPageControl alloc] init];
    _pageControl.currentPage = 0;
    _pageControl.numberOfPages = 1;
    [self addSubview:_pageControl];

    CGFloat insets = (self.frame.size.width - 4 * CHAT_BUTTON_SIZE) / 5;

    _photoButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_photoButton setTitle:@"相册" forState:UIControlStateNormal];//改动
    [_photoButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _photoButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _photoButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _photoButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    _photoButton.accessibilityIdentifier = @"image";
    [_photoButton setFrame:CGRectMake(insets, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//改动
    [_photoButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_photo"] forState:UIControlStateNormal];
    [_photoButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_photoSelected"] forState:UIControlStateHighlighted];
    [_photoButton addTarget:self action:@selector(photoAction) forControlEvents:UIControlEventTouchUpInside];
    _photoButton.tag = MOREVIEW_BUTTON_TAG;
    [_scrollview addSubview:_photoButton];

    _locationButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_locationButton setTitle:@"位置" forState:UIControlStateNormal];//改动
    [_locationButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _locationButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _locationButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _locationButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    _locationButton.accessibilityIdentifier = @"location";
    [_locationButton setFrame:CGRectMake(insets * 2 + CHAT_BUTTON_SIZE, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_locationButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_location"] forState:UIControlStateNormal];
    [_locationButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_locationSelected"] forState:UIControlStateHighlighted];
    [_locationButton addTarget:self action:@selector(locationAction) forControlEvents:UIControlEventTouchUpInside];
    _locationButton.tag = MOREVIEW_BUTTON_TAG + 1;
    [_scrollview addSubview:_locationButton];

    _takePicButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_takePicButton setTitle:@"拍照" forState:UIControlStateNormal];//改动
    [_takePicButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _takePicButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _takePicButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _takePicButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_takePicButton setFrame:CGRectMake(insets * 3 + CHAT_BUTTON_SIZE * 2, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//改动
    [_takePicButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_camera"] forState:UIControlStateNormal];
    [_takePicButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_cameraSelected"] forState:UIControlStateHighlighted];
    [_takePicButton addTarget:self action:@selector(takePicAction) forControlEvents:UIControlEventTouchUpInside];
    _takePicButton.tag = MOREVIEW_BUTTON_TAG + 2;
    _maxIndex = 2;
    [_scrollview addSubview:_takePicButton];

    CGRect frame = self.frame;
    if (type == EMChatToolbarTypeChat) {
    frame.size.height = 150;
    _audioCallButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_audioCallButton setTitle:@"语音" forState:UIControlStateNormal];//改动
    [_audioCallButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _audioCallButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _audioCallButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _audioCallButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_audioCallButton setFrame:CGRectMake(insets * 4 + CHAT_BUTTON_SIZE * 3, 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_audioCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_audioCall"] forState:UIControlStateNormal];
    [_audioCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_audioCallSelected"] forState:UIControlStateHighlighted];
    [_audioCallButton addTarget:self action:@selector(takeAudioCallAction) forControlEvents:UIControlEventTouchUpInside];
    _audioCallButton.tag = MOREVIEW_BUTTON_TAG + 3;
    [_scrollview addSubview:_audioCallButton];

    _videoCallButton =[UIButton buttonWithType:UIButtonTypeCustom];
    [_videoCallButton setTitle:@"视频" forState:UIControlStateNormal];//改动
    [_videoCallButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];//改动
    _videoCallButton.titleLabel.font = [UIFont systemFontOfSize: 12.0];//改动
    _videoCallButton.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 20, 0);//改动
    _videoCallButton.titleEdgeInsets = UIEdgeInsetsMake(14, -60, -20, 0);//改动
    [_videoCallButton setFrame:CGRectMake(insets, 10 * 2 + CHAT_BUTTON_SIZE + 10, CHAT_BUTTON_SIZE , CHAT_BUTTON_SIZE+10)];//
    [_videoCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_videoCall"] forState:UIControlStateNormal];
    [_videoCallButton setImage:[UIImage easeImageNamed:@"EaseUIResource.bundle/chatBar_colorMore_videoCallSelected"] forState:UIControlStateHighlighted];
    [_videoCallButton addTarget:self action:@selector(takeVideoCallAction) forControlEvents:UIControlEventTouchUpInside];
    _videoCallButton.tag =MOREVIEW_BUTTON_TAG + 4;
    _maxIndex = 4;
    [_scrollview addSubview:_videoCallButton];
    }
    else if (type == EMChatToolbarTypeGroup)
    {
    frame.size.height = 80;
    }
    self.frame = frame;
    _scrollview.frame = CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
    _pageControl.frame = CGRectMake(0, CGRectGetHeight(frame) - 20, CGRectGetWidth(frame), 20);
    _pageControl.hidden = _pageControl.numberOfPages<=1;
    }




    本人github:https://github.com/BHAreslee
    本人简书:http://www.jianshu.com/u/bb53043aaa00
    以上就是集成环信时暂时发现的问题,欢迎大家分享你们遇到的问题,也欢迎加入QQ群:372251359,一起讨论交流即时通讯的问题。
    本人微信公众号:放心安慰剂

    qrcode_for_gh_bc92a063b4a2_430.jpg

     
    项目完整源码
    0
    回复

    收到消息的代理回调不会执行 环信 iOS

    回复

    Aries 发起了问题 • 1 人关注 • 470 次浏览 • 2017-09-12 10:28 • 来自相关话题

    0
    评论

    环信公开课16期回放|环信智能鉴黄:用深度学习实现99%精准度的鉴黄服务 环信 环信公开课 环信智能鉴黄 鉴黄

    beyond 发表了文章 • 469 次浏览 • 2017-09-04 17:01 • 来自相关话题

       8月31日,环信公开课以“智能鉴黄”为主题,为大家普及了内容审查工作的前世今生,以及环信智能鉴黄算法、技术实现和行业解决方案。
     
    关于环信智能鉴黄:
       随着移动互联网的飞速发展和信息量的猛增,大量的色情、赌博、暴力等不良信息图片夹杂在信息流中,严重影响着整个互联网的体验和健康发展。各大互联网公司为了保持自己所提供的服务不触犯国家法律和法规,使得鉴黄工作变得尤为重要。环信智能鉴黄服务基于深度学习的智能鉴黄算法,识别精准度高达99%,可以帮助企业完成95%的图片内容审查工作,节省90%的时间及人工成本。
    环信公开课第16期分享内容:


















































    环信公开课第16期视频回放:





    参加环信公开课还有大礼相送:
    恭喜手机尾号8985的leoNN同学成为本期公开课幸运观众,获得环信定制版瑞士军团双肩背包。

    环信智能鉴黄免费体验请联系环信小助手,微信huanxin-hh 查看全部
       8月31日,环信公开课以“智能鉴黄”为主题,为大家普及了内容审查工作的前世今生,以及环信智能鉴黄算法、技术实现和行业解决方案。
     
    关于环信智能鉴黄:

       随着移动互联网的飞速发展和信息量的猛增,大量的色情、赌博、暴力等不良信息图片夹杂在信息流中,严重影响着整个互联网的体验和健康发展。各大互联网公司为了保持自己所提供的服务不触犯国家法律和法规,使得鉴黄工作变得尤为重要。环信智能鉴黄服务基于深度学习的智能鉴黄算法,识别精准度高达99%,可以帮助企业完成95%的图片内容审查工作,节省90%的时间及人工成本。


    环信公开课第16期分享内容:
    001.png


    002.png


    003.png


    004.png


    005.png


    006.png


    007.png


    008.png


    009.png


    010.png


    环信公开课第16期视频回放:






    参加环信公开课还有大礼相送:
    恭喜手机尾号8985的leoNN同学成为本期公开课幸运观众,获得环信定制版瑞士军团双肩背包。

    环信智能鉴黄免费体验请联系环信小助手,微信huanxin-hh
    3a36009c9eb571b9a3a2797f17c4ae25.gif
    1
    评论

    精通环信开发已成程序员招聘刚需?看别人家的招聘要求 环信 招聘

    beyond 发表了文章 • 307 次浏览 • 2017-08-25 15:46 • 来自相关话题

    今天在一个2000人技术交流群里看到一家互联网公司招聘Android/ios开发











    一段不到200字的招聘要求,竟然出现了两次“环信”。眉头一紧,感觉这事不简单了!






    去年在环信社区看到《今天面试一个自称两年经验的Android》《我又做了一次面试官》两篇面试经历还不以为然,没想到一年内作者预言成真,精通环信开发等第三方API开发已然成为程序员招聘刚需!

    作为一个与时俱进的好司机赶紧打开X度搜索“如何精通环信开发”,还真让我找到了环信Alpha全国开发者培训计划,



    环信alpha计划将对所有报名的ISV厂商和开发者提供技术、审核认证及发行等方面的支持。环信“Alpha计划”旨在为ISV和开发者们提供更加全面且专业的支持,帮助其在包括企业IM、协同OA、APP内社交、直播互动、IOT、智能硬件等领域挖掘产生更多落地有商业前景的优质项目,一起建设整个即时通讯云服务生态。

    文末有小伙伴愿意去这家福建公司的发送简历到duc@easemob.com邮箱,暗号“我精通环信开发”,我们等的就是你! 查看全部
    今天在一个2000人技术交流群里看到一家互联网公司招聘Android/ios开发

    TIM截图20170825163121.png


    timg.jpg


    一段不到200字的招聘要求,竟然出现了两次“环信”。眉头一紧,感觉这事不简单了!

    TIM图片20170825160503.jpg


    去年在环信社区看到《今天面试一个自称两年经验的Android》《我又做了一次面试官》两篇面试经历还不以为然,没想到一年内作者预言成真,精通环信开发等第三方API开发已然成为程序员招聘刚需!

    作为一个与时俱进的好司机赶紧打开X度搜索“如何精通环信开发”,还真让我找到了环信Alpha全国开发者培训计划
    TIM截图20170825160913.png
    环信alpha计划将对所有报名的ISV厂商和开发者提供技术、审核认证及发行等方面的支持。环信“Alpha计划”旨在为ISV和开发者们提供更加全面且专业的支持,帮助其在包括企业IM、协同OA、APP内社交、直播互动、IOT、智能硬件等领域挖掘产生更多落地有商业前景的优质项目,一起建设整个即时通讯云服务生态。

    文末有小伙伴愿意去这家福建公司的发送简历到duc@easemob.com邮箱,暗号“我精通环信开发”,我们等的就是你!
    3
    回复

    环信v3,聊天室解除禁言在回调前崩溃的问题 环信 禁言

    XiaoMai 回复了问题 • 2 人关注 • 726 次浏览 • 2017-08-23 14:32 • 来自相关话题

    0
    评论

    【移动战略说 · 第一期】智能硬件产品开发从0到1 环信 行业活动

    beyond 发表了文章 • 196 次浏览 • 2017-08-14 19:09 • 来自相关话题

       据GSMA预期,到2020年,全球互联设备将突破270亿,移动互联设备有望达到105亿,新的市场机遇将进一步增多。自动上报家中燃气数据、远程开关气阀、精准透明计费、自动调节远程定时控制路灯等,基于新一代物联网的新型智慧产品正在走入我们的生产生活。

       开发一款智能硬件产品涉及的环节很多。本次活动,APICloud联合华强聚丰和智石科技,从样品生产、App开发和近场通讯技术在智能硬件中的应用跟大家分享智能硬件产品如何快速从0到1!
     
    活动概况
    【活动时间】2017年8月19日(周六),13:30-16:30
    【面向人群】制造业企业、智能硬件管理层、产品负责人、技术负责人,其他相关从业者
    【活动咨询/合作】请加微信:appdev1,备注819活动议程
    【13:30-14:00】签到
    【14:00-14:40】如何快速完成样品生产
    内容概要:产品硬件开发者希望快速拿到样品,进行方案验证和调试,发现设计问题,快速进行方案修正,以便进入下一开发环节,完成开发工作。怎样解决这些困难?怎样才能让生产环节快速顺利完成样品生产?
    【14:40-15:20】自主研发or外包?智能硬件App开发指南
    内容概要:现在市场上智能硬件往往需要一款App配合,无论是控制设备还是查看数据。企业不但需要考虑成本,还要兼顾产品体验。本环节APICloud将会为大家介绍App开发技术如何选型;自己招团队与找外包的对比;以及项目准备、开发、测试、上线各个阶段可能遇到的问题和注意事项。
    【15:20-16:00】室内精准位置物联网络搭建
    【16:00-】幸运抽奖&自由交流分享嘉宾
















    报名地址活动报名 查看全部
       据GSMA预期,到2020年,全球互联设备将突破270亿,移动互联设备有望达到105亿,新的市场机遇将进一步增多。自动上报家中燃气数据、远程开关气阀、精准透明计费、自动调节远程定时控制路灯等,基于新一代物联网的新型智慧产品正在走入我们的生产生活。

       开发一款智能硬件产品涉及的环节很多。本次活动,APICloud联合华强聚丰和智石科技,从样品生产、App开发和近场通讯技术在智能硬件中的应用跟大家分享智能硬件产品如何快速从0到1!
     
    活动概况
    【活动时间】2017年8月19日(周六),13:30-16:30
    【面向人群】制造业企业、智能硬件管理层、产品负责人、技术负责人,其他相关从业者
    【活动咨询/合作】请加微信:appdev1,备注819
    活动议程
    【13:30-14:00】签到
    【14:00-14:40】如何快速完成样品生产
    内容概要:产品硬件开发者希望快速拿到样品,进行方案验证和调试,发现设计问题,快速进行方案修正,以便进入下一开发环节,完成开发工作。怎样解决这些困难?怎样才能让生产环节快速顺利完成样品生产?
    【14:40-15:20】自主研发or外包?智能硬件App开发指南
    内容概要:现在市场上智能硬件往往需要一款App配合,无论是控制设备还是查看数据。企业不但需要考虑成本,还要兼顾产品体验。本环节APICloud将会为大家介绍App开发技术如何选型;自己招团队与找外包的对比;以及项目准备、开发、测试、上线各个阶段可能遇到的问题和注意事项。
    【15:20-16:00】室内精准位置物联网络搭建
    【16:00-】幸运抽奖&自由交流
    分享嘉宾

    30972779689807524.jpeg


    30242778644313753.jpg


    30852779689957552.jpeg


    报名地址活动报名
    1
    回复

    'EMSDKFull.h' file not found iOS 环信

    wangyuzhang 回复了问题 • 2 人关注 • 585 次浏览 • 2017-08-08 19:46 • 来自相关话题

    0
    评论

    月薪五千和五万销售的区别:一只丑桔引发的大单子(环信真实案例改编) 丑橘 环信

    beyond 发表了文章 • 309 次浏览 • 2017-08-04 17:27 • 来自相关话题

    ​​ 




     这是一个初冬的早晨。王向东迈着轻快的步伐,走进了“黄桃园”集团大楼,直奔物业管理公司CEO陶福成办公室。与陶总交换名片后,陶总看着名片,抬头说:“你就是那个什么环信公司的销售经理?你在电话上说有一笔大生意要谈?简单说说吧,我只有十分钟时间。”陶总抬手看了眼手表。

    王向东从包里拿出一只丑桔,放到大班台上,说:“这是丑桔,想必陶总吃过。”陶总微微点了下头。“我要和陶总谈的生意与丑桔有关。”陶总好奇地问:“我一个物业公司,怎么会和丑桔生意有关呢?”

    “我先问陶总一个经营上的问题。现在由于人工费用上涨很快,物业公司从业主收来的物业费却多年没有做相应的调整,物业公司的利润逐年下滑,甚至出现亏损,不知是不是属实?”陶总点了下头,心里却想你个毛头小子还和我说盈亏,真不知天高地厚。

    “所以物业公司不得不想别的办法,拓展收入来源来弥补物业费的亏空。”陶总一笑:“所以你想推荐丑桔生意?”王向东指着台上的丑桔说:“是的!咱们算笔账。陶总物业公司管理着三个高档小区,一共有3万2千住户。”陶总眼睛从半眯状到睁大状。“丑桔是新开发的一个水果品种,口味独特,很受欢迎,超市里卖到24块每公斤。如果能以18块每公斤卖给您的住户,想必一定卖的很好。如果直接和原产地进货,进货价格是10块每公斤,这样的话毛利是8块每公斤。假设有1万5千住户每户购买一箱20公斤,总共30万公斤,毛利240万。”陶总深深点了下头:“240万不少,但对于我这样的物业公司来说,还真不是什么了不起的收入。”

    “如果我说丑桔贡献240万,精品东北大米贡献300万,陕西红富士苹果贡献300万。。。。。。这些收入合起来贡献2000万毛利,够不够大?”“够大!但是我要把这个生意做成,需要店面,仓库,运输,配送,押款。。。。。。费用支出多大,你知道吗?”

    “知道。但如果我有办法把这些费用降到零呢?”陶总瞪大了眼睛:“什么办法?”“就是利用移动互联技术,构建客服平台,起到一石三鸟作用。”“哪三鸟?”“一是解决咱们物业管理老本行与住户的交流和住户服务请求和相应;二是形成电子商务平台,网上推广产品;三是网上缴费,既交物业费,又是电子商务资金流通道。”

    陶总站起来,拉住王向东的手:“快说说,你能帮我建设这个什么客服平台吗?”“可以,环信就是这方面的专家。”

    陶总快步走到门口,对秘书说:“马上通知总裁办主任,客服部主管,IT部主管,财务部主管到我这里开会!”

    几分钟后,主管们到齐。陶总说:“来,跟大家介绍一下这位小兄弟,王向东,他可是给我们带来了好东西,先听听他的介绍。”王向东站起来谦逊地个跟每个主管打了招呼,才坐下简要地介绍了刚才跟陶总交流的内容。陶总站起来说:“王兄弟带来的方案,揭开了困扰我们好长时间的难题,有了这个客服平台,可以大幅度提高我们的物业服务质量,同时开辟了扩大收入的渠道,是个非常有价值的建议。我要求你们和小王兄弟一起尽快拿出方案,做出预算,在2个月内上线!”

    所有主管都响亮地答应下来,同时心里在猜测这位“小王兄弟”后台有多硬,是陶总的什么关系?

    没过几天,方案出来了,预算也出来了。一期先建设即时通讯软件平台和客户交互平台,建设费用320万;二期建设智能客服机器人系统,建设费用180万;采用vpc形式,每年支付环信托管费用50万;环信提供战略和业务咨询,每年咨询费40万。

    一个由丑桔引起的“大单子”就这么发生了!(由环信真实销售案例改编,文中均为化名) 查看全部
    ​​ 
    timg.jpg

     这是一个初冬的早晨。王向东迈着轻快的步伐,走进了“黄桃园”集团大楼,直奔物业管理公司CEO陶福成办公室。与陶总交换名片后,陶总看着名片,抬头说:“你就是那个什么环信公司的销售经理?你在电话上说有一笔大生意要谈?简单说说吧,我只有十分钟时间。”陶总抬手看了眼手表。

    王向东从包里拿出一只丑桔,放到大班台上,说:“这是丑桔,想必陶总吃过。”陶总微微点了下头。“我要和陶总谈的生意与丑桔有关。”陶总好奇地问:“我一个物业公司,怎么会和丑桔生意有关呢?”

    “我先问陶总一个经营上的问题。现在由于人工费用上涨很快,物业公司从业主收来的物业费却多年没有做相应的调整,物业公司的利润逐年下滑,甚至出现亏损,不知是不是属实?”陶总点了下头,心里却想你个毛头小子还和我说盈亏,真不知天高地厚。

    “所以物业公司不得不想别的办法,拓展收入来源来弥补物业费的亏空。”陶总一笑:“所以你想推荐丑桔生意?”王向东指着台上的丑桔说:“是的!咱们算笔账。陶总物业公司管理着三个高档小区,一共有3万2千住户。”陶总眼睛从半眯状到睁大状。“丑桔是新开发的一个水果品种,口味独特,很受欢迎,超市里卖到24块每公斤。如果能以18块每公斤卖给您的住户,想必一定卖的很好。如果直接和原产地进货,进货价格是10块每公斤,这样的话毛利是8块每公斤。假设有1万5千住户每户购买一箱20公斤,总共30万公斤,毛利240万。”陶总深深点了下头:“240万不少,但对于我这样的物业公司来说,还真不是什么了不起的收入。”

    “如果我说丑桔贡献240万,精品东北大米贡献300万,陕西红富士苹果贡献300万。。。。。。这些收入合起来贡献2000万毛利,够不够大?”“够大!但是我要把这个生意做成,需要店面,仓库,运输,配送,押款。。。。。。费用支出多大,你知道吗?”

    “知道。但如果我有办法把这些费用降到零呢?”陶总瞪大了眼睛:“什么办法?”“就是利用移动互联技术,构建客服平台,起到一石三鸟作用。”“哪三鸟?”“一是解决咱们物业管理老本行与住户的交流和住户服务请求和相应;二是形成电子商务平台,网上推广产品;三是网上缴费,既交物业费,又是电子商务资金流通道。”

    陶总站起来,拉住王向东的手:“快说说,你能帮我建设这个什么客服平台吗?”“可以,环信就是这方面的专家。”

    陶总快步走到门口,对秘书说:“马上通知总裁办主任,客服部主管,IT部主管,财务部主管到我这里开会!”

    几分钟后,主管们到齐。陶总说:“来,跟大家介绍一下这位小兄弟,王向东,他可是给我们带来了好东西,先听听他的介绍。”王向东站起来谦逊地个跟每个主管打了招呼,才坐下简要地介绍了刚才跟陶总交流的内容。陶总站起来说:“王兄弟带来的方案,揭开了困扰我们好长时间的难题,有了这个客服平台,可以大幅度提高我们的物业服务质量,同时开辟了扩大收入的渠道,是个非常有价值的建议。我要求你们和小王兄弟一起尽快拿出方案,做出预算,在2个月内上线!”

    所有主管都响亮地答应下来,同时心里在猜测这位“小王兄弟”后台有多硬,是陶总的什么关系?

    没过几天,方案出来了,预算也出来了。一期先建设即时通讯软件平台和客户交互平台,建设费用320万;二期建设智能客服机器人系统,建设费用180万;采用vpc形式,每年支付环信托管费用50万;环信提供战略和业务咨询,每年咨询费40万。

    一个由丑桔引起的“大单子”就这么发生了!(由环信真实销售案例改编,文中均为化名)
    0
    评论

    【环信征文】|两处小改动,解决环信V3.0官方版本关于转发的bug 转发 即时通讯 环信 IM

    cokeyer 发表了文章 • 276 次浏览 • 2017-08-02 00:57 • 来自相关话题

        (本人github:https://github.com/BHAreslee)(若转载,请告知本人并附上原文链接,谢谢)
        
        最近接手了一个集成即时通讯功能的项目,用的是环信的SDK。用环信的接口可以快速实现即时通讯的很多功能。并且对官方demo稍加改动基本能够满足项目需求。真机测试时,发现图片的转发,每次都是转发失败。我开始以为是我集成时有疏漏,逐行检查代码。发现并不是我的问题。从app store下载的官方demo同样是转发失败!!坑我啊!!原因是ContactListSelectViewController这个控制器里无法正确获取到想转发的图片的缓存地址。
    修改如下图:





    ContactListSelectViewController.m
    代码拷走直接用- (BOOL)messageViewController:(EaseMessageViewController *)viewController
    didLongPressRowAtIndexPath:(NSIndexPath *)indexPath
    {
    id object = [self.dataArray objectAtIndex:indexPath.row];
    if (![object isKindOfClass:[NSString class]]) {
    EaseMessageCell *cell = (EaseMessageCell *)[self.tableView cellForRowAtIndexPath:indexPath];
    //////////////////////////解决转发问题的代码///////////////////////////////
    EMImageMessageBody *imageBody = (EMImageMessageBody*)[cell.model.message body];
    EMMessageBodyType ty = cell.model.bodyType;
    if (ty == EMMessageBodyTypeImage) {
    NSString *str = cell.model.message == nil ? cell.model.thumbnailFileURLPath : [imageBody localPath];
    [[NSUserDefaults standardUserDefaults] setValue:str forKey:@"imgTosand"];
    }
    /////////////////////////解决转发问题的代码////////////////////////
    [cell becomeFirstResponder];
    self.menuIndexPath = indexPath;
    [self showMenuViewController:cell.bubbleView andIndexPath:indexPath messageType:cell.model.bodyType];
    }
    return YES;
    }ContactListSelectViewController是取数据,那么存数据要在ChatViewController控制器做存数据的操作。消息类型写死为EMChatTypeChat,是因为,不论是从单聊界面转发,还是从群聊界面转发,都只能转发给个人,所以这里写死,目前没有问题。
    如下图:





    ChatViewController.m
    代码拷走直接用#pragma mark - EMUserListViewControllerDelegate
    - (void)userListViewController:(EaseUsersListViewController *)userListViewController
    didSelectUserModel:(id<IUserModel>)userModel
    {
    if (!self.messageModel) {
    return;
    }
    if (self.messageModel.bodyType == EMMessageBodyTypeText) {
    EMMessage *message = [EaseSDKHelper sendTextMessage:self.messageModel.text to:userModel.buddy messageType:EMChatTypeChat messageExt:self.messageModel.message.ext];
    __weak typeof(self) weakself = self;
    [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {
    if (!aError) {
    // NSMutableArray *array = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
    UIViewController *chatController = nil;
    #ifdef REDPACKET_AVALABLE
    chatController = [[RedPacketChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #else
    chatController = [[ChatViewController alloc]
    initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #endif
    chatController.title = userModel.nickname.length != 0 ? [userModel.nickname copy] : [userModel.buddy copy];
    // if ([array count] >= 3) {
    // [array removeLastObject];
    // [array removeLastObject];
    // }
    // [array addObject:chatController];
    // [weakself.navigationController setViewControllers:array animated:YES];
    [weakself.navigationController popViewControllerAnimated:YES];
    } else {
    [self showHudInView:self.view hint:Localized(@"transpondFail")];
    }
    }];
    } else if (self.messageModel.bodyType == EMMessageBodyTypeImage) {
    [self showHudInView:self.view hint:Localized(@"transponding")];
    __weak typeof(self) weakSelf = self;
    NSString *localPath = [(EMImageMessageBody *)self.messageModel.message.body thumbnailLocalPath];
    //////////////////////////解决转发问题的代码////////////////////////////
    localPath = [[NSUserDefaults standardUserDefaults] valueForKey:@"imgTosand"];
    //////////////////////////解决转发问题的代码//////////////////////////
    UIImage *image = [UIImage imageWithContentsOfFile:localPath];
    void (^block)() = ^(EMMessage *message){
    EMImageMessageBody *imgBody = (EMImageMessageBody *)message.body;
    NSString *from = [[EMClient sharedClient] currentUsername];
    EMImageMessageBody *newBody = [[EMImageMessageBody alloc] initWithData:nil thumbnailData:[NSData dataWithContentsOfFile:imgBody.thumbnailLocalPath]];
    newBody.thumbnailLocalPath = imgBody.thumbnailLocalPath;
    newBody.thumbnailRemotePath = imgBody.thumbnailRemotePath;
    newBody.remotePath = imgBody.remotePath;
    EMMessage *newMsg = [[EMMessage alloc] initWithConversationID:userModel.buddy from:from to:userModel.buddy body:newBody ext:message.ext];
    // newMsg.chatType = message.chatType;//此为环信代码
    newMsg.chatType = EMChatTypeChat;//这里是我加的
    [[EMClient sharedClient].chatManager sendMessage:newMsg progress:nil completion:^(EMMessage *message, EMError *error) {
    if (error) {
    [weakSelf showHudInView:self.view hint:Localized(@"transpondFail")];
    [weakSelf performSelector:@selector(backAction) withObject:nil afterDelay:1];
    return ;
    }
    [(EMImageMessageBody *)message.body setLocalPath:imgBody.localPath];
    [[EMClient sharedClient].chatManager updateMessage:message completion:nil];

    // NSMutableArray *array = [NSMutableArray arrayWithArray:[weakSelf.navigationController viewControllers]];

    #ifdef REDPACKET_AVALABLE
    RedPacketChatViewController *chatController = [[RedPacketChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #else
    ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #endif
    chatController.title = userModel.nickname.length != 0 ? userModel.nickname : userModel.buddy;
    // if ([array count] >= 3) {
    // [array removeLastObject];
    // [array removeLastObject];
    // }
    // [array addObject:chatController];
    // [weakSelf.navigationController setViewControllers:array animated:YES];
    [weakSelf.navigationController popViewControllerAnimated:YES];//转发完跳回去
    }];
    };

    if (!image) {
    [[EMClient sharedClient].chatManager downloadMessageThumbnail:self.messageModel.message progress:nil completion:^(EMMessage *message, EMError *error) {
    if (error) {
    [weakSelf showHudInView:self.view hint:Localized(@"transpondFail")];
    [weakSelf performSelector:@selector(backAction) withObject:nil afterDelay:1];
    return ;
    }

    block(message);
    }];
    } else {
    block(self.messageModel.message);
    }
    }
    }上面一定要判断一下消息体类型,只有消息体为图片类型(EMMessageBodyTypeImage)才需要保存图片本地。如果不做判断的话,点击气泡马上崩掉。
    个人感觉虽然能解决图片转发的问题,但并不是最好的解决办法,虽然对环信demo的代码改动最少。有更好的办法,欢迎在评论区交流。
    (本人github:https://github.com/BHAreslee)(若转载,请告知本人并附上原文链接,谢谢) 查看全部
        (本人github:https://github.com/BHAreslee)(若转载,请告知本人并附上原文链接,谢谢)
        
        最近接手了一个集成即时通讯功能的项目,用的是环信的SDK。用环信的接口可以快速实现即时通讯的很多功能。并且对官方demo稍加改动基本能够满足项目需求。真机测试时,发现图片的转发,每次都是转发失败。我开始以为是我集成时有疏漏,逐行检查代码。发现并不是我的问题。从app store下载的官方demo同样是转发失败!!坑我啊!!原因是ContactListSelectViewController这个控制器里无法正确获取到想转发的图片的缓存地址。
    修改如下图:

    2893691-7bfd41d8c42b5f3d.png

    ContactListSelectViewController.m
    代码拷走直接用
    - (BOOL)messageViewController:(EaseMessageViewController *)viewController
    didLongPressRowAtIndexPath:(NSIndexPath *)indexPath
    {
    id object = [self.dataArray objectAtIndex:indexPath.row];
    if (![object isKindOfClass:[NSString class]]) {
    EaseMessageCell *cell = (EaseMessageCell *)[self.tableView cellForRowAtIndexPath:indexPath];
    //////////////////////////解决转发问题的代码///////////////////////////////
    EMImageMessageBody *imageBody = (EMImageMessageBody*)[cell.model.message body];
    EMMessageBodyType ty = cell.model.bodyType;
    if (ty == EMMessageBodyTypeImage) {
    NSString *str = cell.model.message == nil ? cell.model.thumbnailFileURLPath : [imageBody localPath];
    [[NSUserDefaults standardUserDefaults] setValue:str forKey:@"imgTosand"];
    }
    /////////////////////////解决转发问题的代码////////////////////////
    [cell becomeFirstResponder];
    self.menuIndexPath = indexPath;
    [self showMenuViewController:cell.bubbleView andIndexPath:indexPath messageType:cell.model.bodyType];
    }
    return YES;
    }
    ContactListSelectViewController是取数据,那么存数据要在ChatViewController控制器做存数据的操作。消息类型写死为EMChatTypeChat,是因为,不论是从单聊界面转发,还是从群聊界面转发,都只能转发给个人,所以这里写死,目前没有问题。
    如下图:

    2893691-7beb949a62e8035f.png

    ChatViewController.m
    代码拷走直接用
    #pragma mark - EMUserListViewControllerDelegate
    - (void)userListViewController:(EaseUsersListViewController *)userListViewController
    didSelectUserModel:(id<IUserModel>)userModel
    {
    if (!self.messageModel) {
    return;
    }
    if (self.messageModel.bodyType == EMMessageBodyTypeText) {
    EMMessage *message = [EaseSDKHelper sendTextMessage:self.messageModel.text to:userModel.buddy messageType:EMChatTypeChat messageExt:self.messageModel.message.ext];
    __weak typeof(self) weakself = self;
    [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {
    if (!aError) {
    // NSMutableArray *array = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
    UIViewController *chatController = nil;
    #ifdef REDPACKET_AVALABLE
    chatController = [[RedPacketChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #else
    chatController = [[ChatViewController alloc]
    initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #endif
    chatController.title = userModel.nickname.length != 0 ? [userModel.nickname copy] : [userModel.buddy copy];
    // if ([array count] >= 3) {
    // [array removeLastObject];
    // [array removeLastObject];
    // }
    // [array addObject:chatController];
    // [weakself.navigationController setViewControllers:array animated:YES];
    [weakself.navigationController popViewControllerAnimated:YES];
    } else {
    [self showHudInView:self.view hint:Localized(@"transpondFail")];
    }
    }];
    } else if (self.messageModel.bodyType == EMMessageBodyTypeImage) {
    [self showHudInView:self.view hint:Localized(@"transponding")];
    __weak typeof(self) weakSelf = self;
    NSString *localPath = [(EMImageMessageBody *)self.messageModel.message.body thumbnailLocalPath];
    //////////////////////////解决转发问题的代码////////////////////////////
    localPath = [[NSUserDefaults standardUserDefaults] valueForKey:@"imgTosand"];
    //////////////////////////解决转发问题的代码//////////////////////////
    UIImage *image = [UIImage imageWithContentsOfFile:localPath];
    void (^block)() = ^(EMMessage *message){
    EMImageMessageBody *imgBody = (EMImageMessageBody *)message.body;
    NSString *from = [[EMClient sharedClient] currentUsername];
    EMImageMessageBody *newBody = [[EMImageMessageBody alloc] initWithData:nil thumbnailData:[NSData dataWithContentsOfFile:imgBody.thumbnailLocalPath]];
    newBody.thumbnailLocalPath = imgBody.thumbnailLocalPath;
    newBody.thumbnailRemotePath = imgBody.thumbnailRemotePath;
    newBody.remotePath = imgBody.remotePath;
    EMMessage *newMsg = [[EMMessage alloc] initWithConversationID:userModel.buddy from:from to:userModel.buddy body:newBody ext:message.ext];
    // newMsg.chatType = message.chatType;//此为环信代码
    newMsg.chatType = EMChatTypeChat;//这里是我加的
    [[EMClient sharedClient].chatManager sendMessage:newMsg progress:nil completion:^(EMMessage *message, EMError *error) {
    if (error) {
    [weakSelf showHudInView:self.view hint:Localized(@"transpondFail")];
    [weakSelf performSelector:@selector(backAction) withObject:nil afterDelay:1];
    return ;
    }
    [(EMImageMessageBody *)message.body setLocalPath:imgBody.localPath];
    [[EMClient sharedClient].chatManager updateMessage:message completion:nil];

    // NSMutableArray *array = [NSMutableArray arrayWithArray:[weakSelf.navigationController viewControllers]];

    #ifdef REDPACKET_AVALABLE
    RedPacketChatViewController *chatController = [[RedPacketChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #else
    ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:userModel.buddy conversationType:EMConversationTypeChat];
    #endif
    chatController.title = userModel.nickname.length != 0 ? userModel.nickname : userModel.buddy;
    // if ([array count] >= 3) {
    // [array removeLastObject];
    // [array removeLastObject];
    // }
    // [array addObject:chatController];
    // [weakSelf.navigationController setViewControllers:array animated:YES];
    [weakSelf.navigationController popViewControllerAnimated:YES];//转发完跳回去
    }];
    };

    if (!image) {
    [[EMClient sharedClient].chatManager downloadMessageThumbnail:self.messageModel.message progress:nil completion:^(EMMessage *message, EMError *error) {
    if (error) {
    [weakSelf showHudInView:self.view hint:Localized(@"transpondFail")];
    [weakSelf performSelector:@selector(backAction) withObject:nil afterDelay:1];
    return ;
    }

    block(message);
    }];
    } else {
    block(self.messageModel.message);
    }
    }
    }
    上面一定要判断一下消息体类型,只有消息体为图片类型(EMMessageBodyTypeImage)才需要保存图片本地。如果不做判断的话,点击气泡马上崩掉。
    个人感觉虽然能解决图片转发的问题,但并不是最好的解决办法,虽然对环信demo的代码改动最少。有更好的办法,欢迎在评论区交流。
    (本人github:https://github.com/BHAreslee)(若转载,请告知本人并附上原文链接,谢谢)
    0
    评论

    环信荣膺“2017未来独角兽企业”,做商业的连接器 独角兽 新闻资讯 环信

    新闻资讯 发表了文章 • 537 次浏览 • 2017-07-25 11:29 • 来自相关话题

     独角兽企业往往聚集了行业里大多的资源,随着技术、人才、资金的积累,其在行业里的地位与机会将逐步放大,前进愈发顺利,发展迎风而起。近日,由中国科学院《互联网周刊》杂志评选的“2017未来独角兽企业TOP150”榜单正式揭晓,有着国际领先的企业级软件服务提供商愿景的环信凭借在即时通讯云和SaaS客服领域的行业深耕和迅猛发展,以全国榜单第130名位居垂直行业第一。




    “连接人与人”,“连接人与商业”的愿景支撑垂直行业第一

       企业服务市场是一块大蛋糕,练就的是技术内功,靠的是对市场趋势的准确把握,环信以用户需求为出发点近期推出客户互动云(CEC),环信CEC基于全球领先的即时通讯云技术,通过人工智能和大数据赋能,依托多渠道接入管理、精准用户画像、智能客服机器人、客户之声、智能质检、视频客服等SaaS客服体系为包括保险、证券、金融、教育、电商等行业提供了从客户互动渠道、到客户服务、再到精准营销的全流程客户互动解决方案。

       环信的起家产品“即时通讯云”,承担环信“连接人与人”的商业愿景,为开发者提供基于移动互联网的即时通讯能力,作为全球最大的即时通讯云厂商已经广泛应用服务13万余APP客户,环信全面支持Android、iOS、Web等多种平台,在流量、电量、长连接、语音、位置、安全等能力做了极致的优化,让移动开发者摆脱繁重的移动IM通讯底层开发,极大限度地缩短产品开发周期,二十四时间内即可让App拥有移动IM能力。目前环信即时通讯云已经拓展推出了包括直播、社交大数据、红包、鉴黄、视频人脸特效、短信验证码等增值服务。

       而“环信移动客服”是即时通讯云“连接人与人”场景的一个延伸到“连接人与商业”,包括网页在线客服、社交媒体客服(微博、微信)、APP内置客服、工单和呼叫中心等多种渠道均可一键接入。基于环信业界领先的IM长连接技术保证消息必达,并通过智能客服机器人技术降低人工客服工作量。同时,基于人工智能和大数据挖掘的客户旅程透析产品”环信客户声音”能够帮助企业优化运营,提高跨渠道客服体验。

       2016年,基于开发即时通讯云和移动客服的基础上,环信对已有产品进行了再次的研发和升级,针对已有在包括电商、保险、证券、金融、教育等优势行业的积累基础上,着手开发人工智能 —— “环信智能客服机器人”。他们希望在不降低用户体验的情况下,尽可能地解决商家日益增长的客服成本和海量客服请求之间的天然矛盾。

       比如,我们在移动端通过国美在线下单后,产品遇到的任何问题,通过IM窗口和客服咨询,这个沟通通道就是环信即时通讯云在提供底层通信服务。环信移动客服依托智能客服机器人很大程度上为企业节约了人力成本,众多保险公司已经通过部署环信智能客服机器人来提高客服效率。环信客户声音提高了跨渠道的客户服务体验,帮助企业优化运营,实现了客户中心完成从成本中心向价值中心的转化,国内某标杆教育机构已经在部署完环信客服声音以后尝到了客户转化率、客单价双升的甜头。

       与此同时,环信还一直利用自己的大数据平台产品给客户提供增值服务,让客户通过即时通讯云和移动客服等产品的后台数据,分析得出自己产品的适用人群、产品体验和活跃度等。让客户能更好地改善自己的产品,更好地服务消费者。

       环信的所有更新、改变与尝试,都是在围绕着一个行业,或者说是一个目标在努力。走上行业的顶峰之后,面临坦途时就会懈怠很多,但他们似乎仍然没有放弃向更高峰的攀登。

       2016年环信作为国内唯一的SaaS厂商荣膺Gartner 2016 Cool Vendor,2017年3月环信刚获得由经纬中国领投、银泰嘉禾跟投的1.03亿元C轮融资,显示出包括国际顶级研究机构和资本市场对于环信商业模式和发展前景的认可。正是得益于包括红杉资本、经纬中国、SIG和银泰嘉禾的鼎力支持,保障了环信持续巨额的研发投入,形成了公司业务发展的正向循环。

    志存高远方能有所大成

       独角兽企业往往聚集了行业里大多的资源,随着技术、人才、资金的积累,其在行业里的地位与机会将逐步放大,前进愈发顺利,发展迎风而起。优势会被放大,引领、变革行业发展的责任则愈发凸显。换句话说,独角兽企业不仅仅是行业的佼佼者,更重要的,它是行业的领跑者、推动者。

       身为未来独角兽企业,要以行业推动者自居,以创新破迷局,以诚信守正心,以担当为己任。只有致力于市场需求的满足,行业发展瓶颈的突破,才会在纷乱的市场竞争中把握准方向,守得住初心,冲出迷雾,把握未来。

    独角兽是一种荣耀的名片,更意味着一种担当与责任。 查看全部
     独角兽企业往往聚集了行业里大多的资源,随着技术、人才、资金的积累,其在行业里的地位与机会将逐步放大,前进愈发顺利,发展迎风而起。近日,由中国科学院《互联网周刊》杂志评选的“2017未来独角兽企业TOP150”榜单正式揭晓,有着国际领先的企业级软件服务提供商愿景的环信凭借在即时通讯云和SaaS客服领域的行业深耕和迅猛发展,以全国榜单第130名位居垂直行业第一。
    ea790d9dly1fhv495ni8gj211j0pyn6b.jpg

    “连接人与人”,“连接人与商业”的愿景支撑垂直行业第一

       企业服务市场是一块大蛋糕,练就的是技术内功,靠的是对市场趋势的准确把握,环信以用户需求为出发点近期推出客户互动云(CEC),环信CEC基于全球领先的即时通讯云技术,通过人工智能和大数据赋能,依托多渠道接入管理、精准用户画像、智能客服机器人、客户之声、智能质检、视频客服等SaaS客服体系为包括保险、证券、金融、教育、电商等行业提供了从客户互动渠道、到客户服务、再到精准营销的全流程客户互动解决方案。

       环信的起家产品“即时通讯云”,承担环信“连接人与人”的商业愿景,为开发者提供基于移动互联网的即时通讯能力,作为全球最大的即时通讯云厂商已经广泛应用服务13万余APP客户,环信全面支持Android、iOS、Web等多种平台,在流量、电量、长连接、语音、位置、安全等能力做了极致的优化,让移动开发者摆脱繁重的移动IM通讯底层开发,极大限度地缩短产品开发周期,二十四时间内即可让App拥有移动IM能力。目前环信即时通讯云已经拓展推出了包括直播、社交大数据、红包、鉴黄、视频人脸特效、短信验证码等增值服务。

       而“环信移动客服”是即时通讯云“连接人与人”场景的一个延伸到“连接人与商业”,包括网页在线客服、社交媒体客服(微博、微信)、APP内置客服、工单和呼叫中心等多种渠道均可一键接入。基于环信业界领先的IM长连接技术保证消息必达,并通过智能客服机器人技术降低人工客服工作量。同时,基于人工智能和大数据挖掘的客户旅程透析产品”环信客户声音”能够帮助企业优化运营,提高跨渠道客服体验。

       2016年,基于开发即时通讯云和移动客服的基础上,环信对已有产品进行了再次的研发和升级,针对已有在包括电商、保险、证券、金融、教育等优势行业的积累基础上,着手开发人工智能 —— “环信智能客服机器人”。他们希望在不降低用户体验的情况下,尽可能地解决商家日益增长的客服成本和海量客服请求之间的天然矛盾。

       比如,我们在移动端通过国美在线下单后,产品遇到的任何问题,通过IM窗口和客服咨询,这个沟通通道就是环信即时通讯云在提供底层通信服务。环信移动客服依托智能客服机器人很大程度上为企业节约了人力成本,众多保险公司已经通过部署环信智能客服机器人来提高客服效率。环信客户声音提高了跨渠道的客户服务体验,帮助企业优化运营,实现了客户中心完成从成本中心向价值中心的转化,国内某标杆教育机构已经在部署完环信客服声音以后尝到了客户转化率、客单价双升的甜头。

       与此同时,环信还一直利用自己的大数据平台产品给客户提供增值服务,让客户通过即时通讯云和移动客服等产品的后台数据,分析得出自己产品的适用人群、产品体验和活跃度等。让客户能更好地改善自己的产品,更好地服务消费者。

       环信的所有更新、改变与尝试,都是在围绕着一个行业,或者说是一个目标在努力。走上行业的顶峰之后,面临坦途时就会懈怠很多,但他们似乎仍然没有放弃向更高峰的攀登。

       2016年环信作为国内唯一的SaaS厂商荣膺Gartner 2016 Cool Vendor,2017年3月环信刚获得由经纬中国领投、银泰嘉禾跟投的1.03亿元C轮融资,显示出包括国际顶级研究机构和资本市场对于环信商业模式和发展前景的认可。正是得益于包括红杉资本、经纬中国、SIG和银泰嘉禾的鼎力支持,保障了环信持续巨额的研发投入,形成了公司业务发展的正向循环。

    志存高远方能有所大成

       独角兽企业往往聚集了行业里大多的资源,随着技术、人才、资金的积累,其在行业里的地位与机会将逐步放大,前进愈发顺利,发展迎风而起。优势会被放大,引领、变革行业发展的责任则愈发凸显。换句话说,独角兽企业不仅仅是行业的佼佼者,更重要的,它是行业的领跑者、推动者。

       身为未来独角兽企业,要以行业推动者自居,以创新破迷局,以诚信守正心,以担当为己任。只有致力于市场需求的满足,行业发展瓶颈的突破,才会在纷乱的市场竞争中把握准方向,守得住初心,冲出迷雾,把握未来。

    独角兽是一种荣耀的名片,更意味着一种担当与责任。
    1
    回复

    关于回话列表 怎么弄啊 环信 Android

    geri_yang 回复了问题 • 2 人关注 • 464 次浏览 • 2017-07-20 18:46 • 来自相关话题

    0
    评论

    在线教育+直播,千亿市场的新入口 环信 APICloud 行业活动

    新闻资讯 发表了文章 • 165 次浏览 • 2017-07-20 11:13 • 来自相关话题

    百度报告显示,互联网教育市场在2016年的增长率位居全行业第三,预计2017年的市场规模将突破2800亿元。AI、VR、AR等新技术的日趋成熟也给产品创新带来了新的可能。在激烈的竞争中,如何提高开发效率,快速将产品推向市场;如何借助前沿技术,给用户带来创新的体验,赢得市场成为企业关注的重点。本次活动,APICloud将联合合作伙伴从在线教育类App的开发及创新技术应用等方向,跟大家聊聊直播给在线教育带来的新机会。




    【活动时间】2017年7月29日(周六),13:30-16:30

    【活动地点】创业邦Demo Space(北京市海淀区中关村创业大街11号海置创投大厦7层)

    【面向人群】在线教育企业管理层、产品负责人、技术负责人,其他在线教育从业者

    【活动咨询/合作】请加微信:appdev1,备注729





    【13:30-14:00】签到

    【14:00-14:40】在线教育App开发面临的挑战

    内容概要:如何冲破在线教育的技术壁垒;在线教育业务落地平台选型对比;在线教育类App实例分析

    【14:40-15:20】视频内容版权保护技术在在线教育中的应用

    内容概要:视频盗版的发现、防范及证据保存,以及如何保护视频内容的版权

    【15:20-16:00】直播和在线教育结合的实践经验

    内容概要:直播和在线教育相结合的特点与好处;直播与线下培训、图文、音频分享的区别与特点;线上直播分享的运营和推广经验;IT 在线教育的未来发展趋势

    【16:00-】幸运抽奖&自由交流
























    活动报名:报名地址 查看全部
    百度报告显示,互联网教育市场在2016年的增长率位居全行业第三,预计2017年的市场规模将突破2800亿元。AI、VR、AR等新技术的日趋成熟也给产品创新带来了新的可能。在激烈的竞争中,如何提高开发效率,快速将产品推向市场;如何借助前沿技术,给用户带来创新的体验,赢得市场成为企业关注的重点。
    本次活动,APICloud将联合合作伙伴从在线教育类App的开发及创新技术应用等方向,跟大家聊聊直播给在线教育带来的新机会。
    30102748471066586.png

    【活动时间】2017年7月29日(周六),13:30-16:30

    【活动地点】创业邦Demo Space(北京市海淀区中关村创业大街11号海置创投大厦7层)

    【面向人群】在线教育企业管理层、产品负责人、技术负责人,其他在线教育从业者

    【活动咨询/合作】请加微信:appdev1,备注729



    01.png

    【13:30-14:00】签到

    【14:00-14:40】在线教育App开发面临的挑战

    内容概要:如何冲破在线教育的技术壁垒;在线教育业务落地平台选型对比;在线教育类App实例分析

    【14:40-15:20】视频内容版权保护技术在在线教育中的应用

    内容概要:视频盗版的发现、防范及证据保存,以及如何保护视频内容的版权

    【15:20-16:00】直播和在线教育结合的实践经验

    内容概要:直播和在线教育相结合的特点与好处;直播与线下培训、图文、音频分享的区别与特点;线上直播分享的运营和推广经验;IT 在线教育的未来发展趋势

    【16:00-】幸运抽奖&自由交流



    02.png

    03.jpg


    04.png


    05.jpeg


    06.jpeg

    活动报名:报名地址
    0
    评论

    经纬熊飞:企业服务行业如何先赢而后战 环信 新闻资讯

    新闻资讯 发表了文章 • 390 次浏览 • 2017-07-04 16:01 • 来自相关话题

       




       企业服务并非科技新兴领域,早在上世纪70年代,美国已出现SAP、微软、Oracle这样的ToB公司,成长为巨头。在国内,由于经济快速增长及人力成本低廉,一直以来,企业服务市场属于少为人知的领域。2012年起,国内GDP增速放缓,人力成本增长问题凸显,同时2013年棱镜门事件后,国内加大去IOE力度,也为企业级服务创业提供了较好的发展土壤。

       经纬创投是最早布局企业服务领域的机构。从2012年开始,经过5 年的探索与沉淀,目前在经纬系布局的近50家企业服务创业项目中,有北森、销售易、七牛、永洪BI、OneAPM、环信、GrowingIO、亿方云、上上签、佳格数据、盖雅工场、Pingcap等已初露锋芒。

       今天的文章来自我们与经纬董事总经理熊飞的一次交流,希望对你有所启发。以下,Enjoy:“企业服务项目到底怎么投?两个核心关键点。

    Q:在我看来,做VC有个能力:当有经验积累后,挑项目的时候,是能够预判出项目发展路径的。但问题在于,当一个项目到了一定的标准,投与不投,是多维度进行判断的。比如Saas,中国Saas目前看来还比较难做,如果满足了基本条件KPI达标,那么超越KPI的标准是什么?在此之上经纬看重什么?

    熊飞:第一点,是个大市场。比如CRM,再比如人力资源,也有很多细分项目,比如做核心人力、做招聘,但肯定不只是做一个报表工具。企业服务公司所处的市场足够大,这是核心。企业服务本身是让企业为该职能相关痛点去付费。而销售、HR、客服、财务等职能,是企业最核心职能,痛点的商业价值最大。所以大市场的基础,是该产品关注的是企业核心职能,以及解决的是核心职能中的核心痛点。

    第二点,要考虑这个项目是不是处在浪尖位置。我们经常说投浪尖。三五年前投Saas,那个时候对于早期项目来说是一个浪尖。过去一两年投infrastructure(IT底层架构),也是个浪尖,比如说marketing automation(营销自动化)、iot等等。所以如果你现在做客服Saas创业就不是浪尖了,因为已有环信这些头部项目。浪尖的优势在于你是最早做的,所有资源都给你。

    总结一下:它应该是这个领域最早的探路者,且速度一直高速增长。如果市场够大,并处于浪尖的位置,是先人半步与先人一步的机会,这个我们是非常看重的。“企业服务,产品技术导向的创始人更有优势。

    Q:在这两点满足的前提下,关于团队层面,有什么体会?你们看重创始人的哪些特质?

    熊飞:我觉得没有完美决策,我们常说VC是一个判断+运气的连续体,但投ToB靠判断会更多一些。做的每一个判断都希望结果是大概率事件,但所谓大概率也只能证明这个项目七八成应该投,但没有百分之百。

    我个人倾向产品技术导向的创始人。在我看来,投产品技术导向的团队没什么下行风险,但上行收益巨大;因为产品技术好,最差情况就是没销售,但优势在于产品壁垒高,一旦市场找到感觉,找到销售合伙人,业务可能就会以5 倍、10倍增速发展。但纯销售导向创始人,早期业务起来比较快,但如果竞争对手是产品技术导向,对手一旦找到市场感觉和销售合伙人,下行风险就很大。

    宏观来看,企业服务公司产品技术的护城河宽不宽,有没有留下足够多的安全边际,是我们很关注的点。这也是经纬系企业服务公司,为什么普遍发展很扎实、高速健康增长的原因。我们在投的时候,是希望跟产品技术导向、着重于打磨自己产品的创始人去沟通。

    Q:说到产品和技术,其实相对难判断,ToC可能是看KPI;ToB的话,特别是一些早期公司除了看创始人过去的背景,怎么去判断呢?

    熊飞:我觉得有几点,第一,做reference track,团队的能力,是可以通过reference相当程度判断。

    第二,团队投每个领域都会投入很多的时间,要了解趋势,知道有哪些领先的公司。形成初步投资假设。再去和公司聊发展、聊产品,就能够比较快的判断出这个团队的视野、产品意识。

    第三,就是一些标杆客户的反馈,这个是实打实的。做到这三点就很快能做出不赖的判断。“先赢而后战。

    Q:经纬五年前就开始布局ToB,坚持到现在。在我看来,五年前的时候应该非常寂寞。直到2015年大家才普遍觉得 ToB是风口,这期间你是怎么去判断的?

    熊飞:投ToB其实投的创始人的特质,往往都是比较踏实、稳重、重逻辑、重积累,团队专注某一个方向;ToC则不然,可能需要创始人是愿意快速变化的人——这两类人是完全不一样的。

    另外,我个人觉得在中国投ToB的长期回报会比美国投ToB好很多。原因在于:

    在美国,因为Salesforce、Workday等已有领先者产品的市场占有度很高,导致创业公司长不动、长不大,很多都是10亿美金、12亿美金被并购。在中国,ToB领域竞争并不激烈,因为没有产品供给,很多公司创业两年,就可以做中国500强的生意,这在美国不可想象。所以从长期来看,国内 ToB创业公司的天花板显著的高。

    另外,从运营效率来看国内Saas创业公司也有不小优势。美国很多Saas公司大概做到1 个亿美金收入还在不停亏损,还要不停地往前赶,很难实现现金流打平。但在国内,至少我们投的很多Saas公司做到亿元人民币量级的时候,或者之后一年,就有机会做到单月盈亏平衡。

    最后,从经纬角度来说,最核心是投产品高壁垒和护城河足够宽的项目,比如像HR领域的北森现在发展很好,五年后还会发展很好、再比如销售易、环信、GrowingIO……这些公司现在很好,我们也能看到它们五年后都会很好。

    大核心、大前提还是投到最优秀的公司。我很喜欢《孙子兵法》里面的一句话——先胜而后战,你要先确保你大概率能赢的再去打。张颖有一句话,叫自强则万强,只要把产品、技术做到行业内非常领先,我觉得融资的问题都是业务问题。“企业服务这么火,创业到底是该切入大客户还是小客户?

    熊飞:经纬投企业服务五年时间,这个行业的发展是超出预期的。几点原因:

    中国人力成本的提高到了一个转折点。我经常举例子,六年前一个人工资大概3000元 / 月,一台电脑5000元。现在反过来了,一个人工资5000元,笔记本电脑的价格只有2000元。企业主是很理性的,以前2:1,现在变1:2了,他希望更大投入提高效率。而且,最近中国经济增长放缓,三年前企业主都在谈拉贷款、扩产能,但是现在想的是如何高效地去提高利润,也落在软件上。

    我有个观察,ToB市场爆发,不是留给海外巨头,而是给国内创业企业的巨大机会。很像七八年前智能手机的市场,当时移动手机市场刚起来,大家知道苹果、三星非常好,可是一台手机要六七千块。所以需求起来的时候,性价比更高的国产手机,小米、OPPO、华为、中兴爆发式增长。ToB领域也类似,软件从最初大型和超大型企业的刚需,过渡到中型以上企业的刚需,而这个爆发的市场更关注性价比和产品体验,使得国内创业公司成为最大受益方。

    Q:那么现在如果再做企业服务创业的话,是否理想的客户反而不是中海油、中石油,而应该是中型企业?

    熊飞:我们投的大部分成功企业服务公司,不是一上来就瞄准中海油等超大型企业,无法一击即中,因为超大型企业的功能需求太多了。它们往往是先瞄准100人到300人的中型企业,或者是中型偏小型企业,要先快速上手,再逐年向上走,今年可能是服务100人到300人的企业,明年可能是300人到800人,后年可能是1000人到2000人。随着功能不断地添加,这是一个“逆流而上”的策略。

    Q:有个现象非常有趣——很多企业服务创业者会在两头摇摆,以前做大客户出身的会非常痛恨做大企业,过去诸如催款、服务等等小事,CEO、工程师动不动就被叫过去处理问题。 经历过做大客户的,现在就愿意做小企业或者中小企业,他觉得我是产品说话,不会像以前那样被牵着鼻子走;但又会发现一个新问题:收费有点困难。小企业消失得快,或者是需求率不高。他们就像一个钟摆在不断摇摆。你怎么看?

    熊飞:我觉得一定要做中大企业。一点一点往上。全球IT投入90% 来自于财富两千强,再90% 来自于两万强,你做不到两万强的生意,你就只有1% 的市场,自然这个公司能够成为一个很大的、很牛的公司的概率也变得很小。“投资的魅力所在:不断地去证伪。

    Q:经纬企业服务团队做的最快的一次决策多长时间?为什么?

    熊飞:最快决策是当天见完觉得可以投,就签下TS。能这么快的原因是,团队在该领域已做了足够多思考,见了足够多公司,当遇到这家公司时,其实是捅破了这层“窗户纸”。

    另外,我认为投资的魅力所在,是一个不断证伪的过程。VC这个行业是一个idea business,所有的回报取决于你的idea质量,本质在于两点:

    第一,generate idea的能力,就是说你的视野够广,经常在一线跑,有很多的思考。

    第二,证伪idea的能力。如果你没有证伪idea的能力,那就变成了自己做空中楼阁的假设。

    经纬企业服务团队每天都在不断地拼命去证伪——比如17年初定了三四个ToB的主方向,现在看有两个觉得不错;但是已有一个觉得机会不大,还有一个待判断。所以每个季度都在推翻自己投资的思路和假设。

    Q:Peter Thiel的书《Zero to One》里说过创投要有一个非常规的想法。如果说你提一个跟ToB相关的观点,比如“我觉得我这么认为,但是其他的投资人未必是这么认为的”。如果有,是什么?

    熊飞:我觉得是中国企业服务创业公司机会规模,10倍于目前美国企业服务创业机会。原因在于,美国在enterprise是三波的创业浪潮,第一波是上世纪70年代到80年代,像SAP、微软、Oracle,他们现在都是1000亿到3000亿美金的公司。第二波是云计算,从上世纪90年代末到2000下半叶,这时崛起了Salesforce、workday、NetSuite、ServiceNow这一系列公司,从几十亿美金到六百亿美金。第三波就是现在,现在有一些AI企业服务创业公司开始起来。

    在中国,这三波发展是融合在一起爆发的,三、四年前没有人谈企业服务,现在所有人都在谈企业服务,所有人都在谈企业服务直接上云计算,所有人都在谈企业服务和AI的结合。所以三波浪潮的合并,使得目前中国企业服务创业公司的天花板显著的高。

    Q:会不会有这样一个趋势,SAP这些公司等于是压在中国公司头上的石头,首先会有一批企业服务本土企业。未来中国公司出海,反过来最后会不会变成中国公司把SAP干掉?

    熊飞:第一,我不知道会不会干掉,但我相信未来的5 到10年中国的企业服务公司会在全球企业服务市场将占据重要地位,原因有两点:一是随着中国企业的出海而出海;二是价格优势,SAP、Oracle现在是一个85分到90分的产品,但我们中国的企业服务产品现在很努力地在赶上,虽然可能还是一个75分的产品,但是价格是其1 /3。三是,未来中国企业的最佳实践,会成为第三世界国家(企业服务下一波机会所在地)的最佳实践。 查看全部
       
    201707039141499064337064.jpg

       企业服务并非科技新兴领域,早在上世纪70年代,美国已出现SAP、微软、Oracle这样的ToB公司,成长为巨头。在国内,由于经济快速增长及人力成本低廉,一直以来,企业服务市场属于少为人知的领域。2012年起,国内GDP增速放缓,人力成本增长问题凸显,同时2013年棱镜门事件后,国内加大去IOE力度,也为企业级服务创业提供了较好的发展土壤。

       经纬创投是最早布局企业服务领域的机构。从2012年开始,经过5 年的探索与沉淀,目前在经纬系布局的近50家企业服务创业项目中,有北森、销售易、七牛、永洪BI、OneAPM、环信、GrowingIO、亿方云、上上签、佳格数据、盖雅工场、Pingcap等已初露锋芒。

       今天的文章来自我们与经纬董事总经理熊飞的一次交流,希望对你有所启发。以下,Enjoy:“企业服务项目到底怎么投?两个核心关键点。

    Q:在我看来,做VC有个能力:当有经验积累后,挑项目的时候,是能够预判出项目发展路径的。但问题在于,当一个项目到了一定的标准,投与不投,是多维度进行判断的。比如Saas,中国Saas目前看来还比较难做,如果满足了基本条件KPI达标,那么超越KPI的标准是什么?在此之上经纬看重什么?

    熊飞:第一点,是个大市场。比如CRM,再比如人力资源,也有很多细分项目,比如做核心人力、做招聘,但肯定不只是做一个报表工具。企业服务公司所处的市场足够大,这是核心。企业服务本身是让企业为该职能相关痛点去付费。而销售、HR、客服、财务等职能,是企业最核心职能,痛点的商业价值最大。所以大市场的基础,是该产品关注的是企业核心职能,以及解决的是核心职能中的核心痛点。

    第二点,要考虑这个项目是不是处在浪尖位置。我们经常说投浪尖。三五年前投Saas,那个时候对于早期项目来说是一个浪尖。过去一两年投infrastructure(IT底层架构),也是个浪尖,比如说marketing automation(营销自动化)、iot等等。所以如果你现在做客服Saas创业就不是浪尖了,因为已有环信这些头部项目。浪尖的优势在于你是最早做的,所有资源都给你。

    总结一下:它应该是这个领域最早的探路者,且速度一直高速增长。如果市场够大,并处于浪尖的位置,是先人半步与先人一步的机会,这个我们是非常看重的。“企业服务,产品技术导向的创始人更有优势。

    Q:在这两点满足的前提下,关于团队层面,有什么体会?你们看重创始人的哪些特质?

    熊飞:我觉得没有完美决策,我们常说VC是一个判断+运气的连续体,但投ToB靠判断会更多一些。做的每一个判断都希望结果是大概率事件,但所谓大概率也只能证明这个项目七八成应该投,但没有百分之百。

    我个人倾向产品技术导向的创始人。在我看来,投产品技术导向的团队没什么下行风险,但上行收益巨大;因为产品技术好,最差情况就是没销售,但优势在于产品壁垒高,一旦市场找到感觉,找到销售合伙人,业务可能就会以5 倍、10倍增速发展。但纯销售导向创始人,早期业务起来比较快,但如果竞争对手是产品技术导向,对手一旦找到市场感觉和销售合伙人,下行风险就很大。

    宏观来看,企业服务公司产品技术的护城河宽不宽,有没有留下足够多的安全边际,是我们很关注的点。这也是经纬系企业服务公司,为什么普遍发展很扎实、高速健康增长的原因。我们在投的时候,是希望跟产品技术导向、着重于打磨自己产品的创始人去沟通。

    Q:说到产品和技术,其实相对难判断,ToC可能是看KPI;ToB的话,特别是一些早期公司除了看创始人过去的背景,怎么去判断呢?

    熊飞:我觉得有几点,第一,做reference track,团队的能力,是可以通过reference相当程度判断。

    第二,团队投每个领域都会投入很多的时间,要了解趋势,知道有哪些领先的公司。形成初步投资假设。再去和公司聊发展、聊产品,就能够比较快的判断出这个团队的视野、产品意识。

    第三,就是一些标杆客户的反馈,这个是实打实的。做到这三点就很快能做出不赖的判断。“先赢而后战。

    Q:经纬五年前就开始布局ToB,坚持到现在。在我看来,五年前的时候应该非常寂寞。直到2015年大家才普遍觉得 ToB是风口,这期间你是怎么去判断的?

    熊飞:投ToB其实投的创始人的特质,往往都是比较踏实、稳重、重逻辑、重积累,团队专注某一个方向;ToC则不然,可能需要创始人是愿意快速变化的人——这两类人是完全不一样的。

    另外,我个人觉得在中国投ToB的长期回报会比美国投ToB好很多。原因在于:

    在美国,因为Salesforce、Workday等已有领先者产品的市场占有度很高,导致创业公司长不动、长不大,很多都是10亿美金、12亿美金被并购。在中国,ToB领域竞争并不激烈,因为没有产品供给,很多公司创业两年,就可以做中国500强的生意,这在美国不可想象。所以从长期来看,国内 ToB创业公司的天花板显著的高。

    另外,从运营效率来看国内Saas创业公司也有不小优势。美国很多Saas公司大概做到1 个亿美金收入还在不停亏损,还要不停地往前赶,很难实现现金流打平。但在国内,至少我们投的很多Saas公司做到亿元人民币量级的时候,或者之后一年,就有机会做到单月盈亏平衡。

    最后,从经纬角度来说,最核心是投产品高壁垒和护城河足够宽的项目,比如像HR领域的北森现在发展很好,五年后还会发展很好、再比如销售易、环信、GrowingIO……这些公司现在很好,我们也能看到它们五年后都会很好。

    大核心、大前提还是投到最优秀的公司。我很喜欢《孙子兵法》里面的一句话——先胜而后战,你要先确保你大概率能赢的再去打。张颖有一句话,叫自强则万强,只要把产品、技术做到行业内非常领先,我觉得融资的问题都是业务问题。“企业服务这么火,创业到底是该切入大客户还是小客户?

    熊飞:经纬投企业服务五年时间,这个行业的发展是超出预期的。几点原因:

    中国人力成本的提高到了一个转折点。我经常举例子,六年前一个人工资大概3000元 / 月,一台电脑5000元。现在反过来了,一个人工资5000元,笔记本电脑的价格只有2000元。企业主是很理性的,以前2:1,现在变1:2了,他希望更大投入提高效率。而且,最近中国经济增长放缓,三年前企业主都在谈拉贷款、扩产能,但是现在想的是如何高效地去提高利润,也落在软件上。

    我有个观察,ToB市场爆发,不是留给海外巨头,而是给国内创业企业的巨大机会。很像七八年前智能手机的市场,当时移动手机市场刚起来,大家知道苹果、三星非常好,可是一台手机要六七千块。所以需求起来的时候,性价比更高的国产手机,小米、OPPO、华为、中兴爆发式增长。ToB领域也类似,软件从最初大型和超大型企业的刚需,过渡到中型以上企业的刚需,而这个爆发的市场更关注性价比和产品体验,使得国内创业公司成为最大受益方。

    Q:那么现在如果再做企业服务创业的话,是否理想的客户反而不是中海油、中石油,而应该是中型企业?

    熊飞:我们投的大部分成功企业服务公司,不是一上来就瞄准中海油等超大型企业,无法一击即中,因为超大型企业的功能需求太多了。它们往往是先瞄准100人到300人的中型企业,或者是中型偏小型企业,要先快速上手,再逐年向上走,今年可能是服务100人到300人的企业,明年可能是300人到800人,后年可能是1000人到2000人。随着功能不断地添加,这是一个“逆流而上”的策略。

    Q:有个现象非常有趣——很多企业服务创业者会在两头摇摆,以前做大客户出身的会非常痛恨做大企业,过去诸如催款、服务等等小事,CEO、工程师动不动就被叫过去处理问题。 经历过做大客户的,现在就愿意做小企业或者中小企业,他觉得我是产品说话,不会像以前那样被牵着鼻子走;但又会发现一个新问题:收费有点困难。小企业消失得快,或者是需求率不高。他们就像一个钟摆在不断摇摆。你怎么看?

    熊飞:我觉得一定要做中大企业。一点一点往上。全球IT投入90% 来自于财富两千强,再90% 来自于两万强,你做不到两万强的生意,你就只有1% 的市场,自然这个公司能够成为一个很大的、很牛的公司的概率也变得很小。“投资的魅力所在:不断地去证伪。

    Q:经纬企业服务团队做的最快的一次决策多长时间?为什么?

    熊飞:最快决策是当天见完觉得可以投,就签下TS。能这么快的原因是,团队在该领域已做了足够多思考,见了足够多公司,当遇到这家公司时,其实是捅破了这层“窗户纸”。

    另外,我认为投资的魅力所在,是一个不断证伪的过程。VC这个行业是一个idea business,所有的回报取决于你的idea质量,本质在于两点:

    第一,generate idea的能力,就是说你的视野够广,经常在一线跑,有很多的思考。

    第二,证伪idea的能力。如果你没有证伪idea的能力,那就变成了自己做空中楼阁的假设。

    经纬企业服务团队每天都在不断地拼命去证伪——比如17年初定了三四个ToB的主方向,现在看有两个觉得不错;但是已有一个觉得机会不大,还有一个待判断。所以每个季度都在推翻自己投资的思路和假设。

    Q:Peter Thiel的书《Zero to One》里说过创投要有一个非常规的想法。如果说你提一个跟ToB相关的观点,比如“我觉得我这么认为,但是其他的投资人未必是这么认为的”。如果有,是什么?

    熊飞:我觉得是中国企业服务创业公司机会规模,10倍于目前美国企业服务创业机会。原因在于,美国在enterprise是三波的创业浪潮,第一波是上世纪70年代到80年代,像SAP、微软、Oracle,他们现在都是1000亿到3000亿美金的公司。第二波是云计算,从上世纪90年代末到2000下半叶,这时崛起了Salesforce、workday、NetSuite、ServiceNow这一系列公司,从几十亿美金到六百亿美金。第三波就是现在,现在有一些AI企业服务创业公司开始起来。

    在中国,这三波发展是融合在一起爆发的,三、四年前没有人谈企业服务,现在所有人都在谈企业服务,所有人都在谈企业服务直接上云计算,所有人都在谈企业服务和AI的结合。所以三波浪潮的合并,使得目前中国企业服务创业公司的天花板显著的高。

    Q:会不会有这样一个趋势,SAP这些公司等于是压在中国公司头上的石头,首先会有一批企业服务本土企业。未来中国公司出海,反过来最后会不会变成中国公司把SAP干掉?

    熊飞:第一,我不知道会不会干掉,但我相信未来的5 到10年中国的企业服务公司会在全球企业服务市场将占据重要地位,原因有两点:一是随着中国企业的出海而出海;二是价格优势,SAP、Oracle现在是一个85分到90分的产品,但我们中国的企业服务产品现在很努力地在赶上,虽然可能还是一个75分的产品,但是价格是其1 /3。三是,未来中国企业的最佳实践,会成为第三世界国家(企业服务下一波机会所在地)的最佳实践。
    0
    评论

    《IT经理世界》特写:环信的Alpha刘,布局未来的商业智能! 新闻资讯 IT经理世界 环信 刘俊彦

    新闻资讯 发表了文章 • 373 次浏览 • 2017-06-27 11:21 • 来自相关话题

    6月20号刊

    新疆界




    刘俊彦说不想做一家小老头公司——规模不大,每年挣个几千万元,日子过得滋润,但每年只有10%左右的增长。

    技术男刘俊彦的思维很跳跃,2014年做即时通讯云,一年后开始做客服云,不到一年,又开辟了智能机器人业务。看起来好像在分片作战,但突然有一天他已经在一个更大的战略布局里了。

    这些年,云的概念被炒到火热,企业不惜花血本布局云计算,可一轮下来之后,不同的业务还是要各养一套人马,各养一套软件系统,说好的大数据,量是上去了,但是实际利用率却如挤牙膏,效用微乎其微。很多企业现在正处在一个升级也不是,不升级也不是的难受期。

    见到刘俊彦的时候,他刚送走一家航空公司的几位管理人员,他们现在的烦恼是,守着一大批高净值的用户,只能卖个机票,最多再卖个保险,利润已经碰到天花板,有种守着宝藏却挖不出金子的感觉。刘俊彦在他的小会议室的黑板上,画了一个完整的从用户服务到用户营销的闭环图,这张图里包含了航空公司乃至一些大企业当下的几大痛点及应对招数,如同在下一盘围棋,细节处棋势做得够厚,大局又跳出常人思维之外,细看与AlphaGo的风格颇为相似。

    这是刘俊彦第一次将自己成熟的大局想法展示给外界。
     
    高效融资与快速换挡
     
    刘俊彦毕业于英国伦敦大学国王学院计算机专业,后一直在IT外企从事技术研发工作,2013年,离职创业前已经成为红帽开源软件领域领先的专家。这一年,他已经年过40。

    最初的一年多时间,是在海淀图书城的车库咖啡里度过的,当时刘俊彦和另外三位合伙人都刚从外企里出来,各自都已经是行业里优秀的技术人才,都实现了财务自由,清楚自己要的是什么,且志趣相投,所以走到了一起。

    刚开始,大家专注于做产品,也没有急着去找投资。一年后,一个偶然的机会,投资自己找上了门。

    2014年5月,刘俊彦他们进驻到氪空间的当天下午,经纬的投资人找到了他们,大概聊了两个多小时,双方就达成了合作意向。紧接着不到半年,SIG和红杉资本相继成为投资方。几家投资方看中的是刘俊彦等人创立的环信公司在即时通讯领域的开发能力和社交大数据分析能力,以及环信自主研发的高并发可扩展架构。

    此前,刘俊彦拥有17年的开发经验,其擅长的领域在于实时消息系统和高并发消息中间件等。2013年,社交软件开始大行其道,当时很多人找他为APP开发即时通讯聊天功能,一般如果企业自己开发的话,怎么都需要好几个月时间,而使用刘俊彦的团队的产品只需一天功夫就出来了。因此,最初的产品并非他们刻意做出来的,而是需求在先,而且令他们也没想到的是,做着做着就成“风口”了。

    很快,使用了环信即时通讯功能的APP上的用户从几万飞速上升到几千万,乃至后来的几个亿,每天下发的消息达20亿条。曾经在短信高峰时代,中国移动每天的消息量是7亿,目前国内能支撑并发连接几千万的团队不超过5个,包括腾讯、阿里、新浪微博、陌陌等,另外还有一个就是环信。

    用户上去之后,新的需求又来了。开始,很多人只是把APP内的聊天功能用作连接人与人的社交管道,但很快就不断有人找上门来,希望把APP内的聊天功能做成淘宝旺旺那样连接人和商业的客服工具。

    从本质上来讲,环信早期推出的即时通讯云是基于PaaS平台的服务,而要做客服云则需建立在SaaS平台上,如此跨平台的转变,对于一家创业公司,无论是人才、资本、研发或渠道等各方面都会带来严峻的挑战。

    2015年4月,A轮的三家投资方在前几个轮次共900万美元的基础上,再次追加了共1250万美元的B轮投资,在资本方的财力和战略加持下,一个月后,环信客服产品线上市,一年后环信客服产品的客户量、销售额等硬指标均达到几十倍上百倍的增长。

    据刘俊彦介绍,早期客服云的客户几乎一半多来自即时通讯云,相当于后者是前者的流量导入渠道,后者反过来巩固了前者的价值所在。

    目前,环信客服产品的企业用户已经超过5万多家,用户也从国美在线、58到家、新东方等扩展到了十几个行业当中。

    然而,IT业一年相当于传统行业十年,这是一个变换以秒速推进的行业,刘俊彦很快又迎上了新的挑战。

    痛点与前瞻

    随着产品的积累和行业的扩展,刘俊彦开始接触到一些保险、证券、航空等行业大客户。曾经有一家保险公司的客户跟他提到亲身经历的一件事情,以往保险公司客户经理做客户维护的通常做法就是每年会定期提前一两个月给老客户打电话,提醒他们保险快到期,可以续费了。其中有一个老客户,关系维护得挺好,但是这个老客户最近新买了辆哈雷摩托车,而他的客户经理没能及时了解并提供摩托车的保险报价,结果错失了老用户。

    这种个案在保险公司普遍存在。如果有更懂用户的数据,进行再分析和精准营销,就能很快帮老用户接上新的业务,还可以把以前让利给渠道的部分,直接反馈给用户,大幅提高销售成功率。

    刘俊彦说,做即时通讯,做客服,真正的差距在于,怎么通过商业智能帮助企业去挖掘以前看不到的客户信息,提高销售转换率,发掘新销售机会,以及人工智能技术怎么代替人工,怎么帮企业营销,这都是未来技术。

    2016年年初,环信基于企业一体化智能商业的需求,开始推全媒体智能客户服务。所谓全媒体就是不管客服请求来自微信、微博或APP,还是网页或电话,都可以同时呈现在一个界面上,由专人统一处理。

    以前企业不同的渠道由不同的人马在支持,各自软件系统也不一样,信息也是各自孤立的,片段化的,环信做到了让一个支持人员同时监控所有渠道,客户身份也可以从孤立的信息中关联起来,形成一个统一身份。也就是说,同一个用户打完电话,再用微信接入,通过各种技术方法可以跨屏身份合并被识别为是同一个人。

    此外,一家企业如果每天进来10万条消息,环信的技术可以识别出来自不同渠道不同数据格式的信息,然后对其进行数据清理,再做主题分析和情感分析,从而知道用户今天都反馈了什么问题,情感是愤怒还是高兴,可能的消费趋势是什么?进一步还可以給出用户画像,画像信息详尽,一直可追溯到用户城市、职业、性别、喜好、消费能力、行为轨迹,等等。

    这些数据对于企业至关重要。不仅是保险公司,证券公司、航空公司等等行业都存在类似的强烈需求。

    环信还在自己研发客服机器人。刘俊彦认为,环信既有SaaS客服软件高市场占有率的通道优势,又有了大量的数据积累,加上对垂直行业的深度理解,在开发具有高度行业特征的客服机器人上,又领先了其他对手。

    2017年 ,环信整合旗下即时通信云、移动客服、智能客服机器人和主动营销产品线,推出环信CEC (Customer Engagement Cloud),向企业提供从客户互动渠道,到客户服务,再到精准客户营销的全流程客户互动解决方案。

    技术出身的刘俊彦,既可以不断挖掘出用户的痛点,在技术细节上下足功夫,又可以跳出来,把握住前瞻性技术,果断出击。当一个个看似不大相关的痛点技术在量的积累上突破一个爆发性临界点时,全新的需求与应用又把之前所有的技术关联在了一起。

    这一切使得刘俊彦像一个“做局”的高手。

    转变与坚持

    创业仅仅4年,刘俊彦已经看惯了互联网领域的迎来送往,2014年,他还经常在微信里看见做社交应用的CEO们发朋友圈,到2015年左右,这些人大多看不到了,换了一批做O2O的CEO,一年以后,这些人又看不见踪影了。大浪淘沙,互联网的残酷淘汰是铁律。

    当年那些做即时通讯服务的环信的老对手们,现在大多还在做老业务,日子过得还不错。刘俊彦却早已不在当初的格局里了。

    做即时通讯云有一个特点,从几十万用户到几百万用户是一个技术节点,从几百万到几千万又是一个节点,用户过亿之后则是一个更大的节点。每一个节点处,基本上架构要推倒重写一遍。这要求技术团队快速的迭代和积累,一旦有一个环节出问题,就有可能导致服务不可用。

    这期间,环信团队也经历了重大考验,也被客户骂过,好在最后都坚持过来了。现在环信即时通讯技术架构早已稳定下来,即使再扩容4~5倍也不成问题。

    然而,就在这么一个节点上,刘俊彦毅然决定再另外做一个SaaS平台,这对于整个团队是一种怎样的震撼。虽然对于技术能力强悍的环信团队来讲,技术难题最终都是可以克服的,而对市场的敏锐嗅觉以及果断决策,却非易事。事实上刘俊彦的判断是精准的。

    环信最初的客户群主要集中在互联网领域,这些客户的生命周期比较短,付费能力比较低,好处是决策周期短,商业谈判简单,能迅速达成交易,迅速验证需求,这适合早期创业。

    有了这段经历也让刘俊彦开始明白,为什么美国的SaaS软件同行们天天讲生命周期价值,讲内容营销,因为他们也跟环信一样做的是小客户,可见对于小客户这一招中外通吃。而大客户不是这么玩的。

    在美国做企业服务,底层有一批创业公司,天花板是做到几亿美元到几十亿美元市值,基本很难再往上突破了。这是因为大客户都被微软、甲骨文、Salesforce这样的公司牢牢掌握着,小企业根本没机会进入那个圈子。

    某种程度上,中国也差不多,但也有很大不同。中国大型企业还没有强大的科技公司可以很好地服务于他们,这些年主要依赖于一些大型系统集成商,系统集成商的做法跟甲骨文等这些科技巨头又不一样,他们以项目运行的方式推进,在创新和积累上相对较弱。

    以前中国的大型国企或私企也认可这种做法,但随着整体经济环境进入L型经济,增长放缓,企业追求利润的结果就是更加注重创新,尤其是服务创新,这两年刘俊彦明显地感觉到国内大型企业有一种创新急迫感,他意识到谁能服务中国500强企业,谁就会成为中国的甲骨文。

    由于求稳,当年环信的竞争对手就没赶上这波新的机会。“如果我们到现在还只是在做最初的一个业务,我们也就成为了一家小老头公司。”刘俊彦平静地说。

    2017年3月,环信完成1.03亿元的C轮融资,由经纬领投,银泰嘉禾跟投。

    当然,考验仍然存在。SaaS是一种功能密集型的技术,最考验大规模研发团队的研发效率和管理能力。2016年新组建的智能机器人团队则是资本密集型,这个团队虽然人不多,但是一年投入却上千万元。

    不同的技术、人才、资本结构,对于管理是一大考验。不过刘俊彦认为,既然创业就要全力以赴去做,“挖人要看眼光,选择很重要,路线很重要,信任也很重要,既然选择上了火箭飞船,就不要考虑是几等舱。”
     作者 | 刘晓芳

    微信编辑 | 李昊原

    原文发表于《IT经理世界》,转载请注明 查看全部

    微信图片_20170627113413.gif
    6月20号刊

    新疆界

    微信图片_20170627111638.jpg

    刘俊彦说不想做一家小老头公司——规模不大,每年挣个几千万元,日子过得滋润,但每年只有10%左右的增长。

    技术男刘俊彦的思维很跳跃,2014年做即时通讯云,一年后开始做客服云,不到一年,又开辟了智能机器人业务。看起来好像在分片作战,但突然有一天他已经在一个更大的战略布局里了。

    这些年,云的概念被炒到火热,企业不惜花血本布局云计算,可一轮下来之后,不同的业务还是要各养一套人马,各养一套软件系统,说好的大数据,量是上去了,但是实际利用率却如挤牙膏,效用微乎其微。很多企业现在正处在一个升级也不是,不升级也不是的难受期。

    见到刘俊彦的时候,他刚送走一家航空公司的几位管理人员,他们现在的烦恼是,守着一大批高净值的用户,只能卖个机票,最多再卖个保险,利润已经碰到天花板,有种守着宝藏却挖不出金子的感觉。刘俊彦在他的小会议室的黑板上,画了一个完整的从用户服务到用户营销的闭环图,这张图里包含了航空公司乃至一些大企业当下的几大痛点及应对招数,如同在下一盘围棋,细节处棋势做得够厚,大局又跳出常人思维之外,细看与AlphaGo的风格颇为相似。

    这是刘俊彦第一次将自己成熟的大局想法展示给外界。
     
    高效融资与快速换挡
     
    刘俊彦毕业于英国伦敦大学国王学院计算机专业,后一直在IT外企从事技术研发工作,2013年,离职创业前已经成为红帽开源软件领域领先的专家。这一年,他已经年过40。

    最初的一年多时间,是在海淀图书城的车库咖啡里度过的,当时刘俊彦和另外三位合伙人都刚从外企里出来,各自都已经是行业里优秀的技术人才,都实现了财务自由,清楚自己要的是什么,且志趣相投,所以走到了一起。

    刚开始,大家专注于做产品,也没有急着去找投资。一年后,一个偶然的机会,投资自己找上了门。

    2014年5月,刘俊彦他们进驻到氪空间的当天下午,经纬的投资人找到了他们,大概聊了两个多小时,双方就达成了合作意向。紧接着不到半年,SIG和红杉资本相继成为投资方。几家投资方看中的是刘俊彦等人创立的环信公司在即时通讯领域的开发能力和社交大数据分析能力,以及环信自主研发的高并发可扩展架构。

    此前,刘俊彦拥有17年的开发经验,其擅长的领域在于实时消息系统和高并发消息中间件等。2013年,社交软件开始大行其道,当时很多人找他为APP开发即时通讯聊天功能,一般如果企业自己开发的话,怎么都需要好几个月时间,而使用刘俊彦的团队的产品只需一天功夫就出来了。因此,最初的产品并非他们刻意做出来的,而是需求在先,而且令他们也没想到的是,做着做着就成“风口”了。

    很快,使用了环信即时通讯功能的APP上的用户从几万飞速上升到几千万,乃至后来的几个亿,每天下发的消息达20亿条。曾经在短信高峰时代,中国移动每天的消息量是7亿,目前国内能支撑并发连接几千万的团队不超过5个,包括腾讯、阿里、新浪微博、陌陌等,另外还有一个就是环信。

    用户上去之后,新的需求又来了。开始,很多人只是把APP内的聊天功能用作连接人与人的社交管道,但很快就不断有人找上门来,希望把APP内的聊天功能做成淘宝旺旺那样连接人和商业的客服工具。

    从本质上来讲,环信早期推出的即时通讯云是基于PaaS平台的服务,而要做客服云则需建立在SaaS平台上,如此跨平台的转变,对于一家创业公司,无论是人才、资本、研发或渠道等各方面都会带来严峻的挑战。

    2015年4月,A轮的三家投资方在前几个轮次共900万美元的基础上,再次追加了共1250万美元的B轮投资,在资本方的财力和战略加持下,一个月后,环信客服产品线上市,一年后环信客服产品的客户量、销售额等硬指标均达到几十倍上百倍的增长。

    据刘俊彦介绍,早期客服云的客户几乎一半多来自即时通讯云,相当于后者是前者的流量导入渠道,后者反过来巩固了前者的价值所在。

    目前,环信客服产品的企业用户已经超过5万多家,用户也从国美在线、58到家、新东方等扩展到了十几个行业当中。

    然而,IT业一年相当于传统行业十年,这是一个变换以秒速推进的行业,刘俊彦很快又迎上了新的挑战。

    痛点与前瞻

    随着产品的积累和行业的扩展,刘俊彦开始接触到一些保险、证券、航空等行业大客户。曾经有一家保险公司的客户跟他提到亲身经历的一件事情,以往保险公司客户经理做客户维护的通常做法就是每年会定期提前一两个月给老客户打电话,提醒他们保险快到期,可以续费了。其中有一个老客户,关系维护得挺好,但是这个老客户最近新买了辆哈雷摩托车,而他的客户经理没能及时了解并提供摩托车的保险报价,结果错失了老用户。

    这种个案在保险公司普遍存在。如果有更懂用户的数据,进行再分析和精准营销,就能很快帮老用户接上新的业务,还可以把以前让利给渠道的部分,直接反馈给用户,大幅提高销售成功率。

    刘俊彦说,做即时通讯,做客服,真正的差距在于,怎么通过商业智能帮助企业去挖掘以前看不到的客户信息,提高销售转换率,发掘新销售机会,以及人工智能技术怎么代替人工,怎么帮企业营销,这都是未来技术。

    2016年年初,环信基于企业一体化智能商业的需求,开始推全媒体智能客户服务。所谓全媒体就是不管客服请求来自微信、微博或APP,还是网页或电话,都可以同时呈现在一个界面上,由专人统一处理。

    以前企业不同的渠道由不同的人马在支持,各自软件系统也不一样,信息也是各自孤立的,片段化的,环信做到了让一个支持人员同时监控所有渠道,客户身份也可以从孤立的信息中关联起来,形成一个统一身份。也就是说,同一个用户打完电话,再用微信接入,通过各种技术方法可以跨屏身份合并被识别为是同一个人。

    此外,一家企业如果每天进来10万条消息,环信的技术可以识别出来自不同渠道不同数据格式的信息,然后对其进行数据清理,再做主题分析和情感分析,从而知道用户今天都反馈了什么问题,情感是愤怒还是高兴,可能的消费趋势是什么?进一步还可以給出用户画像,画像信息详尽,一直可追溯到用户城市、职业、性别、喜好、消费能力、行为轨迹,等等。

    这些数据对于企业至关重要。不仅是保险公司,证券公司、航空公司等等行业都存在类似的强烈需求。

    环信还在自己研发客服机器人。刘俊彦认为,环信既有SaaS客服软件高市场占有率的通道优势,又有了大量的数据积累,加上对垂直行业的深度理解,在开发具有高度行业特征的客服机器人上,又领先了其他对手。

    2017年 ,环信整合旗下即时通信云、移动客服、智能客服机器人和主动营销产品线,推出环信CEC (Customer Engagement Cloud),向企业提供从客户互动渠道,到客户服务,再到精准客户营销的全流程客户互动解决方案。

    技术出身的刘俊彦,既可以不断挖掘出用户的痛点,在技术细节上下足功夫,又可以跳出来,把握住前瞻性技术,果断出击。当一个个看似不大相关的痛点技术在量的积累上突破一个爆发性临界点时,全新的需求与应用又把之前所有的技术关联在了一起。

    这一切使得刘俊彦像一个“做局”的高手。

    转变与坚持

    创业仅仅4年,刘俊彦已经看惯了互联网领域的迎来送往,2014年,他还经常在微信里看见做社交应用的CEO们发朋友圈,到2015年左右,这些人大多看不到了,换了一批做O2O的CEO,一年以后,这些人又看不见踪影了。大浪淘沙,互联网的残酷淘汰是铁律。

    当年那些做即时通讯服务的环信的老对手们,现在大多还在做老业务,日子过得还不错。刘俊彦却早已不在当初的格局里了。

    做即时通讯云有一个特点,从几十万用户到几百万用户是一个技术节点,从几百万到几千万又是一个节点,用户过亿之后则是一个更大的节点。每一个节点处,基本上架构要推倒重写一遍。这要求技术团队快速的迭代和积累,一旦有一个环节出问题,就有可能导致服务不可用。

    这期间,环信团队也经历了重大考验,也被客户骂过,好在最后都坚持过来了。现在环信即时通讯技术架构早已稳定下来,即使再扩容4~5倍也不成问题。

    然而,就在这么一个节点上,刘俊彦毅然决定再另外做一个SaaS平台,这对于整个团队是一种怎样的震撼。虽然对于技术能力强悍的环信团队来讲,技术难题最终都是可以克服的,而对市场的敏锐嗅觉以及果断决策,却非易事。事实上刘俊彦的判断是精准的。

    环信最初的客户群主要集中在互联网领域,这些客户的生命周期比较短,付费能力比较低,好处是决策周期短,商业谈判简单,能迅速达成交易,迅速验证需求,这适合早期创业。

    有了这段经历也让刘俊彦开始明白,为什么美国的SaaS软件同行们天天讲生命周期价值,讲内容营销,因为他们也跟环信一样做的是小客户,可见对于小客户这一招中外通吃。而大客户不是这么玩的。

    在美国做企业服务,底层有一批创业公司,天花板是做到几亿美元到几十亿美元市值,基本很难再往上突破了。这是因为大客户都被微软、甲骨文、Salesforce这样的公司牢牢掌握着,小企业根本没机会进入那个圈子。

    某种程度上,中国也差不多,但也有很大不同。中国大型企业还没有强大的科技公司可以很好地服务于他们,这些年主要依赖于一些大型系统集成商,系统集成商的做法跟甲骨文等这些科技巨头又不一样,他们以项目运行的方式推进,在创新和积累上相对较弱。

    以前中国的大型国企或私企也认可这种做法,但随着整体经济环境进入L型经济,增长放缓,企业追求利润的结果就是更加注重创新,尤其是服务创新,这两年刘俊彦明显地感觉到国内大型企业有一种创新急迫感,他意识到谁能服务中国500强企业,谁就会成为中国的甲骨文。

    由于求稳,当年环信的竞争对手就没赶上这波新的机会。“如果我们到现在还只是在做最初的一个业务,我们也就成为了一家小老头公司。”刘俊彦平静地说。

    2017年3月,环信完成1.03亿元的C轮融资,由经纬领投,银泰嘉禾跟投。

    当然,考验仍然存在。SaaS是一种功能密集型的技术,最考验大规模研发团队的研发效率和管理能力。2016年新组建的智能机器人团队则是资本密集型,这个团队虽然人不多,但是一年投入却上千万元。

    不同的技术、人才、资本结构,对于管理是一大考验。不过刘俊彦认为,既然创业就要全力以赴去做,“挖人要看眼光,选择很重要,路线很重要,信任也很重要,既然选择上了火箭飞船,就不要考虑是几等舱。”
     
    作者 | 刘晓芳

    微信编辑 | 李昊原

    原文发表于《IT经理世界》,转载请注明
    1
    回复

    Android 会话列表只展示群组 Android 环信

    geri_yang 回复了问题 • 2 人关注 • 498 次浏览 • 2017-06-21 12:49 • 来自相关话题

    0
    回复

    android 3.0以后怎么获取自定义消息中Ext消息 环信 ext 接收消息 3.0 Android

    回复

    ╰☆╮末↘ 发起了问题 • 1 人关注 • 449 次浏览 • 2017-06-16 10:30 • 来自相关话题

    0
    评论

    云安全fun享会 | 第三期 《未知安全威胁的检测与防御》 环信 活动 云锁

    新闻资讯 发表了文章 • 375 次浏览 • 2017-06-09 14:41 • 来自相关话题

    活动时间:2017年06月24日 13:30—16:30
    活动地点:北京市朝阳区酒仙桥北路9号恒通国际创新园C8栋 MeePark







       WannaCry、Struts 2等安全事件告诉我们,用规则去防御安全漏洞永远比黑客慢一步,如何在与黑客抗争中先知先觉,占据主动地位,是未来信息安全战争的关键!

       云安全fun享会第三期《未知安全威胁的检测与防御》,邀请业界安全专家,与您分享沙盒、RASP、蜜罐、安全态势感知等对抗未知威胁的利器。

    与其惧怕0day,不如来听听我们的安全沙龙!








    椒图科技助理总经理 吴康
    《利用沙盒检测加密及未知WebShell》




    云锁产品总监 田强
    《RASP技术在中国的落地与实践》
    更多议题陆续添加中,也欢迎您的议题投稿:lidong@jowto.com






    2017年06月24日 13:30
    北京朝阳区酒仙桥北路9号恒通国际创新园C8栋 MeePark
    除了精彩的议题外,我们还准备点心和礼品,等你到来
    会务联络:sunyx@jowto.com




























    本次fun享会活动场地由 MEE-PARK 智能活动空间提供,特此感谢。






    活动报名:报名地址 查看全部
    活动时间:2017年06月24日 13:30—16:30
    活动地点:北京市朝阳区酒仙桥北路9号恒通国际创新园C8栋 MeePark


    01.jpg


       WannaCry、Struts 2等安全事件告诉我们,用规则去防御安全漏洞永远比黑客慢一步,如何在与黑客抗争中先知先觉,占据主动地位,是未来信息安全战争的关键!

       云安全fun享会第三期《未知安全威胁的检测与防御》,邀请业界安全专家,与您分享沙盒、RASP、蜜罐、安全态势感知等对抗未知威胁的利器。

    与其惧怕0day,不如来听听我们的安全沙龙!
    02.png

    03.jpg

    椒图科技助理总经理 吴康
    《利用沙盒检测加密及未知WebShell》


    04.jpg

    云锁产品总监 田强
    《RASP技术在中国的落地与实践》


    更多议题陆续添加中,也欢迎您的议题投稿:lidong@jowto.com


    05.png

    2017年06月24日 13:30
    北京朝阳区酒仙桥北路9号恒通国际创新园C8栋 MeePark
    除了精彩的议题外,我们还准备点心和礼品,等你到来
    会务联络:sunyx@jowto.com

    06.jpg


    07.jpg

    08.jpg


    09.png

    10.jpg


    11.png

    本次fun享会活动场地由 MEE-PARK 智能活动空间提供,特此感谢。
    12.png



    活动报名:报名地址