如何通过呼叫中心发现客户变化?

    我们如何更好的以客户为中心?一种方法是听完所有客户通话记录,阅读所有客户邮件,从客户角度看待问题并理解客户意见,之后直接询问客户问题。很明显,企业无法听完所有通话记录,并且客户调查涉及许多方法,每种方法都各有利弊。
   客户分析能够通过为语音分析、文本分析和客户反馈调查提供软件应用来解决这些问题。这些应用是人力资源优化战略的组成部分,这个战略是由分析驱动的,能提供关键的、全新的客户中心视角。因为它们基于公用的人力资源优化平台,可以分享数据,你的组织能够从数据的协同效益中受益。
GM)`8K~ORA~A(M_Y(_QCRKN.png

语音分析

   语音分析是当下的热门话题,这种兴奋很容易理解。呼叫中心记录了不计其数的客户通话,但是只有一小部分能被听完。此外,他们更注意坐席人员的表现,而非客户。就算组织有意识把关注的重点转移到客户身上,但是只听如此少的谈话记录也不足以充分了解客户的话语和感受,很容易产生误解。

   如果你愿意,语音分析解决方案可以“听”到所有通话记录。这个方案使用了多种技术和算法来索引和记录谈话,让所有谈话都能被搜到。使用索引技术,语音分析就能把记录下的对话按照兴趣的类别进行分类——投诉电话、转移呼叫和情感呼叫。接着,语音分析用算法把与兴趣相类似的单词或短语分门别类,提示呼叫的根本原因。
除了区分原因,语音分析还自动跟踪趋势和变化。按照日、周甚至更长的时间间隔,语音分析可以提醒你它所监测到的相关类别、措辞和短语的变化。

   有个关于德国外包商为他的客户提供语音分析的例子。一天,外包商的语音分析解决方案显示电话数量急剧增加——从零飙升至几百——且含有以下词语“blah, blah, blah”。更为奇怪的是,这些通话的平均时长是一般通话的3倍。分析结果十分骇人。起初,他们认为是一些坐席人员在使用奇怪的词语。但在检查了一些新类别中的通话记录之后,他们很快发现,客户收到了一封来自于市场部的信,解释了服务合同中的一些新特点。这封信十分晦涩难懂,促使很多客户打来电话说:“我收到了一封信,说我的服务发生了变化blah, blah, blah,我不明白这封信到底是什么意思。”外包商立刻通知市场部,这些问题很快就得到了澄清。

QQ图片20170119165210.png

文本分析

   如今,客户的“声音”并非仅限于呼叫中心。越来越多的客户通过智能手机发送文本信息(SMS)。在反复尝试解决问题而未果后,他们就会沮丧,进而转向社交网站,如Facebook和专业投诉网站

   重点是,客户不仅仅是在谈论你的公司;他们写信给你的同时还在写关于你的事。了解顾客写出来的“声音”就需要使用专注于内部和外部的文本通讯分析工具。这正是文本分析的职责。这些解决方案使用自然的语言处理算法和方法以采集和分析电子邮件、网络聊天和社交媒体网站上的帖子。
虽然监视公共网站和需要密码的网站很有趣并且很具话题性,但是大部分内容都无关具体的某个企业。网络是一个浩瀚的海洋,深邃无比,耗费大量时间进行分析也不一定可以获得有益的见解。
相反,组织自身的文本档案仓库就像是一个大湖泊,是有限的。它存有许多来自客户的邮件、调查、网络反馈对话等等文本。所有这些,尽管数量也十分庞大,但都集中关注于你自己的企业,是了解客户的很丰富的资源。文本分析——特别是与语音分析共同使用时——能让组织把从客户邮件和语音记录中获得的有用信息结合起来,得到许多可操作性的信息。
QQ图片20170119165253.png

客户反馈调查

   在高度竞争化的时代,征求客户反馈意见非常重要,不能被忽视,也不能执行不力。客户分析解决方案使用简短的、对文本十分敏感的动态的调查来捕捉客户对产品、流程和员工表现的意见。它能提供十分有价值的“由外之内”的观点评估客户的意见,让呼叫中心和市场部门通过电话和网络获得客户的看法。如果能被正确执行,这些调查就能够取得很好的效果,提供关于员工、流程和情绪的宝贵信息。在把衡量坐席人员业绩表现的调查结果与内部质量监控进行比对时,客户反馈调查会特别有帮助。
QQ图片20170119165330.png

客户分析的附加价值主张

   虽然客户分析提供了以上价值,但是还有其他两个特殊的益处。越来越多的公司希望能更好的处理与他们相关的评论。如果能把文本和语音分析结合起来使用,就可以提供各种各样早期的预警系统。公司可以标记出新出现的问题,及时解决,避免负面信息的爆发。

   另一种特殊的价值主张通过语音分析和质量监控的集成来实现。当语音分析处理并把录音分类保存在数据库中时,质量监控和指导就可以启动——甚至能够超额进行。为什么呢?因为通过高密度的对通话的分类,主管和坐席人员能够准确找到典型的或者涉及工作所需技巧和行为的记录。无论哪种方式,拥有实在的例子能让呼叫中心采取高针对性的指导和培训,进而带来很好的效果。

   最终,客户分析可以提供深刻的洞察力以推动更好的决策。通过把这种洞察力和其他措施相结合,就能获得对客户服务、体验和满意度的360度全方位视角——在不断变化的客户人口统计数据和情绪变动中更有效地发展。
 
本文转自:天华东航运营中心
继续阅读 »
    我们如何更好的以客户为中心?一种方法是听完所有客户通话记录,阅读所有客户邮件,从客户角度看待问题并理解客户意见,之后直接询问客户问题。很明显,企业无法听完所有通话记录,并且客户调查涉及许多方法,每种方法都各有利弊。
   客户分析能够通过为语音分析、文本分析和客户反馈调查提供软件应用来解决这些问题。这些应用是人力资源优化战略的组成部分,这个战略是由分析驱动的,能提供关键的、全新的客户中心视角。因为它们基于公用的人力资源优化平台,可以分享数据,你的组织能够从数据的协同效益中受益。
GM)`8K~ORA~A(M_Y(_QCRKN.png

语音分析

   语音分析是当下的热门话题,这种兴奋很容易理解。呼叫中心记录了不计其数的客户通话,但是只有一小部分能被听完。此外,他们更注意坐席人员的表现,而非客户。就算组织有意识把关注的重点转移到客户身上,但是只听如此少的谈话记录也不足以充分了解客户的话语和感受,很容易产生误解。

   如果你愿意,语音分析解决方案可以“听”到所有通话记录。这个方案使用了多种技术和算法来索引和记录谈话,让所有谈话都能被搜到。使用索引技术,语音分析就能把记录下的对话按照兴趣的类别进行分类——投诉电话、转移呼叫和情感呼叫。接着,语音分析用算法把与兴趣相类似的单词或短语分门别类,提示呼叫的根本原因。
除了区分原因,语音分析还自动跟踪趋势和变化。按照日、周甚至更长的时间间隔,语音分析可以提醒你它所监测到的相关类别、措辞和短语的变化。

   有个关于德国外包商为他的客户提供语音分析的例子。一天,外包商的语音分析解决方案显示电话数量急剧增加——从零飙升至几百——且含有以下词语“blah, blah, blah”。更为奇怪的是,这些通话的平均时长是一般通话的3倍。分析结果十分骇人。起初,他们认为是一些坐席人员在使用奇怪的词语。但在检查了一些新类别中的通话记录之后,他们很快发现,客户收到了一封来自于市场部的信,解释了服务合同中的一些新特点。这封信十分晦涩难懂,促使很多客户打来电话说:“我收到了一封信,说我的服务发生了变化blah, blah, blah,我不明白这封信到底是什么意思。”外包商立刻通知市场部,这些问题很快就得到了澄清。

QQ图片20170119165210.png

文本分析

   如今,客户的“声音”并非仅限于呼叫中心。越来越多的客户通过智能手机发送文本信息(SMS)。在反复尝试解决问题而未果后,他们就会沮丧,进而转向社交网站,如Facebook和专业投诉网站

   重点是,客户不仅仅是在谈论你的公司;他们写信给你的同时还在写关于你的事。了解顾客写出来的“声音”就需要使用专注于内部和外部的文本通讯分析工具。这正是文本分析的职责。这些解决方案使用自然的语言处理算法和方法以采集和分析电子邮件、网络聊天和社交媒体网站上的帖子。
虽然监视公共网站和需要密码的网站很有趣并且很具话题性,但是大部分内容都无关具体的某个企业。网络是一个浩瀚的海洋,深邃无比,耗费大量时间进行分析也不一定可以获得有益的见解。
相反,组织自身的文本档案仓库就像是一个大湖泊,是有限的。它存有许多来自客户的邮件、调查、网络反馈对话等等文本。所有这些,尽管数量也十分庞大,但都集中关注于你自己的企业,是了解客户的很丰富的资源。文本分析——特别是与语音分析共同使用时——能让组织把从客户邮件和语音记录中获得的有用信息结合起来,得到许多可操作性的信息。
QQ图片20170119165253.png

客户反馈调查

   在高度竞争化的时代,征求客户反馈意见非常重要,不能被忽视,也不能执行不力。客户分析解决方案使用简短的、对文本十分敏感的动态的调查来捕捉客户对产品、流程和员工表现的意见。它能提供十分有价值的“由外之内”的观点评估客户的意见,让呼叫中心和市场部门通过电话和网络获得客户的看法。如果能被正确执行,这些调查就能够取得很好的效果,提供关于员工、流程和情绪的宝贵信息。在把衡量坐席人员业绩表现的调查结果与内部质量监控进行比对时,客户反馈调查会特别有帮助。
QQ图片20170119165330.png

客户分析的附加价值主张

   虽然客户分析提供了以上价值,但是还有其他两个特殊的益处。越来越多的公司希望能更好的处理与他们相关的评论。如果能把文本和语音分析结合起来使用,就可以提供各种各样早期的预警系统。公司可以标记出新出现的问题,及时解决,避免负面信息的爆发。

   另一种特殊的价值主张通过语音分析和质量监控的集成来实现。当语音分析处理并把录音分类保存在数据库中时,质量监控和指导就可以启动——甚至能够超额进行。为什么呢?因为通过高密度的对通话的分类,主管和坐席人员能够准确找到典型的或者涉及工作所需技巧和行为的记录。无论哪种方式,拥有实在的例子能让呼叫中心采取高针对性的指导和培训,进而带来很好的效果。

   最终,客户分析可以提供深刻的洞察力以推动更好的决策。通过把这种洞察力和其他措施相结合,就能获得对客户服务、体验和满意度的360度全方位视角——在不断变化的客户人口统计数据和情绪变动中更有效地发展。
 
本文转自:天华东航运营中心 收起阅读 »

单技能专席与多技能普席的策略选择

    《孙子兵法》中有一句脍炙人口的话:“凡战者,以正合,以奇胜。”奇正之用,由2500多年前流传至今,已经成为中国式谋略的一个重要手段,而且备受当今的商业社会推崇。兵法原意是,在以正兵与敌人交战的时候,永远要多埋伏一支多出来的兵力,谓之奇兵。奇兵能出其不意,战斗中突然打乱敌人的部署,是致胜的关键,这也是“分战法”的基本法则。

  纵观目前客户服务中心,通常会设有单技能的专席和多技能的普通座席,设置专席的理由也很简单,就是为了集中部分专业人员去解决一些普通座席无法做得更好的事情,或为某类特殊客户群体提供专门服务,如通信行业的话费专席、金融行业的理财专席等。但是设立专席也往往出现共性的问题,就是专席利用率不高,不如全技能普通座席复用方式,可以满足任何时期的服务资源不足的问题,于是原单技能的专席变成了加载多技能的普席,以应对资源不足情况,这种做法貌似是解决了资源不足的问题,但又出现了专席不专的情况,甚至慢慢的专席被撤离,重新回到大而全的多技能普席状况。带着这些问题,笔者尝试进一步剖析单技能专席与多技能普通座席的策略利弊,并阐述两种模式技能座席如何进行切换。

一、专席设立的目的与原则 (奇正之用)

   正本溯源,首先我们从专席设立的目的和方式着手研究。专席的设立是客户联络中心运营策略的重要组成部分,核心是“合适的时间选择合适的人做合适的事情”。大多数企业在业务规模不大或建立之初,一般选择组建全技能普通座席作为生产运营的主力,可称之为“正兵”。

   全技能普通座席的建立可以实现全员识业务、懂系统的运营需求,也可在短时间内调用生产资源,来满足服务资源不足的问题。但随着业务量的增长、服务规模的扩大,多技能普通座席的运营弊端开始显现。
以通信运营商的客户联络中心为例,多技能普通座席存在的弊端如下:

   1、业务量增长迅速,人员需掌握的知识内容多:电信运营商业务种类量级都有数百个或上千个,每个业务再细分不同的知识点,需要上万个文档进行汇编。如果采用复合型普通座席承接,人员需掌握的知识数量过于庞大,因而很难精通全部业务内容,无法成为万能的“专家”。

   2、团队流失率较高,人员职业素质良莠不齐:一般呼叫中心话务员平均流失率在3%-5%,年流失率在20%-30%之间,如果不考虑业务萎缩或新增情况,人员流失后需要补充新的资源进来,而一名新员工从入职到熟练过程需要6个月到12月时间,由于“生手”的存在一定会导致客户的服务感知存在偏差。
  
   3、客户需求呈多样化,快速响应要求高:现在客户需求明显呈多层次化,他们开始关注品质服务、尊享服务、增值服务、延伸服务等精神上的需求,普通座席由于服务对象较多,即使目前已经可以实现大数据标签筛选,再通过弹窗方式识别客户,但很难在技能上完全匹配客户需求,或服务成效不明显。

   此时,就如同用兵作战,我们需要用奇兵取胜,组建一支装备精良的突击队伍(专席),为新形势下产生的新问题或新产品提供服务,进而解决多技能普通座席所面临的“不专”问题。

  首先,我们在组建专席后,可以通过人员集中培训、问题集中反馈推进,快速打造作战队伍,在其作战(服务)方式成熟顺畅后,通过经验模板的沉淀,再传递给作战的主力军即普通座席,进而形成有效的服务配合体系。

 

当然,专席的建立因需要有独立的生产资源,会对客户联络中心的整体运营产生一定的资源耗损,但笔者认为,如果专席的建立能有效支持公司核心战略业务发展或重要客户保障工作,提供更专业更优质的服务,那搭建专席就是有价值且值得投入资源运营的。专席的核心价值,在于集中精力快速解决客户问题,我们称之为运营策略中的“奇兵”,但是,正奇是会随着时间推演而发生变化,比如专席数量越来越庞大,后面会再做进一步的阐述。

   其次,要打造具备有战斗力的奇兵,不是简单的圈一堆人就可以了,需要在业务界定、运作流程、人员选拔等方面进行思考,以便更好的支撑专席运作。

1、圈业务:专席承接业务内容的圈定,首先要考虑公司内外部环境的变化情况,内部环境需要考虑公司战略发展方向,外部环境需要考虑市场竞争形势及客户需求的变化;其次要从业务角度考虑,优先解决复杂、长流程或客户群体较重要的业务。另外,在业务圈定的过程中,需确保被筛选的话务类型便于识别,进而降低一线识别难度及客户的入线门槛。

2、定流程:武器装备是发挥作战效能的关键,专席需要在具备常规装备的基础上,同时具备更为精良、丰富的作战武器。具体在运营上可体现为以下三个方面:其一,专席人员使用的支撑系统及人员操作权限上需更加完备,用于支撑人员解决普席无法解决的各类疑难杂症;其二,专席需与业务管理等后台部门建立更为完善、顺畅的跨部门沟通流程,以便高效开展各类服务运营工作;其三,专席需具备更加丰富、有力的客户声音传递渠道,便于有效解决客户反馈的业务服务短板。

3、选专人:专席承接的是业务难度大、客户咨询细致的高端业务,要求专席代表具备较强的业务素质和学习能力,因此专席代表的选拔不建议采用新人,而是通过对人员绩效、工作年限、实操能力及对专席兴趣的考量,在多技能普通座席人员中选拔。另外,人员在培养阶段,需要有一套完善的培训体系及认证标准,使之与专席定位高度匹配,让专席成为优秀普席代表晋升的途径之一。

二、专席与普席的衔接关系(奇正之变)

   用兵作战注重的是战略部署的灵活多变,客户联络中心的运营也需要做动态调整,其实专席运营策略也是如此,存在奇正之变。

  以笔者所在的广东移动客户服务中心为例,在专席运营过程中,角色定位也发生了三个阶段的演进。

1、引入阶段,专席为奇

  初级的服务策略1.0时期,专席是作战的奇兵,该时期客户需求量少,服务入口识别方便性、座席配置均处于基础搭建阶段,为了保障客户接入感知,一般会采用多技能普通座席转接专席的方式。如广东移动客户服务中心宽带专席,业务发展初期,客户需求通过10086主服务入口进入,通过在线转接的方式传递给专席,此时普席为服务的第一窗口,而专席就是服务的后备奇兵。

2、成长阶段,专席为正

  随着业务发展,客户需求量逐步增加,专席需要从后台走向前台,成为作战的主力军,由“奇兵”成长为“正兵”,也就进入了专席服务策略2.0时期。此阶段,专席人员服务流程较为顺畅、各类运营策略趋于成熟、服务经验也在逐步沉淀,专席处于飞速成长时期。还是以广东移动宽带专席为例,在服务提升时期,我们建立了移动光宽带服务热线1008616,并在10086主渠道下增加宽带服务入口,通过IVR服务策略的配置,实现全量宽带需求直接进入专席,成为面向客户提供服务的第一窗口。

3、成熟阶段,奇正之和

   当业务进入成熟期后,专席数量越来越庞大,由于规模过大出现专席投入资源不足或知识点不断扩大的问题,也就意味着,此时专席充当主力的作战(服务)模式需要做进一步调整,专席服务策略将进入精耕细作的3.0时期,即专席与普席为奇正之和的协同作战(服务)模式。

   当客户拨打服务热线时,通过IVR入线策略将客户的需求进行第一层的辨别,简单服务需求通过路由配置进入普通座席,更高服务技能的复杂服务需求(如故障处理、投诉等)则进入专家专席。同时如普通座席客服代表在服务过程中遇到无法解决的问题,可在线转接至专家座席,由专家团队给予支撑。
QQ图片20170119152935.png

席服务策略演进的三个阶段

   当然,做好专席与普席的衔接,除了有精准客户识别能力以外,重点要打通专席与普席话务转接功能,可查看双方资源闲置状态,避免转接失败和等待给客户带来的不良感知。在话务协同方面,需要在业务管理、投诉管理、营销管理、系统支撑、业务流程优化等方面有明确的协同规范,以更好的支持两种运营模式的衔接。

   综合所述,我们可以看到单技能专席与多技能普通座席的策略选择问题,其实是一个不断变化调整的过程,是所有客户联络中心需要注重运营的动态平衡问题,也是兵法所说的“诡”,即能根据实际情况而随时变化。
 
三、未来展望

   笔者认为,专席的建立,肩负的不仅仅是普通座席的职能,更应该向着“更专业、更优质、更标杆”的目标前进。

   随着人工智能技术的兴起,未来客户联络中心不但是人工专席与普席之间的策略选择问题,更多是在于前端智能机器人与后端人工服务的区别方式,但智能机器人方式解决更多是原有普通座席简单可以处理的问题,相信在未来,对于人工专席的要求会更高,如何让人工价值更加显性,需要我们更多的关注和研究。

本文刊载于《客户世界》2016年12月刊文章;原文作者李俊凡、李雪梅,本文作者单位为中国移动广东公司 客户服务(佛山)中心。
继续阅读 »
    《孙子兵法》中有一句脍炙人口的话:“凡战者,以正合,以奇胜。”奇正之用,由2500多年前流传至今,已经成为中国式谋略的一个重要手段,而且备受当今的商业社会推崇。兵法原意是,在以正兵与敌人交战的时候,永远要多埋伏一支多出来的兵力,谓之奇兵。奇兵能出其不意,战斗中突然打乱敌人的部署,是致胜的关键,这也是“分战法”的基本法则。

  纵观目前客户服务中心,通常会设有单技能的专席和多技能的普通座席,设置专席的理由也很简单,就是为了集中部分专业人员去解决一些普通座席无法做得更好的事情,或为某类特殊客户群体提供专门服务,如通信行业的话费专席、金融行业的理财专席等。但是设立专席也往往出现共性的问题,就是专席利用率不高,不如全技能普通座席复用方式,可以满足任何时期的服务资源不足的问题,于是原单技能的专席变成了加载多技能的普席,以应对资源不足情况,这种做法貌似是解决了资源不足的问题,但又出现了专席不专的情况,甚至慢慢的专席被撤离,重新回到大而全的多技能普席状况。带着这些问题,笔者尝试进一步剖析单技能专席与多技能普通座席的策略利弊,并阐述两种模式技能座席如何进行切换。

一、专席设立的目的与原则 (奇正之用)

   正本溯源,首先我们从专席设立的目的和方式着手研究。专席的设立是客户联络中心运营策略的重要组成部分,核心是“合适的时间选择合适的人做合适的事情”。大多数企业在业务规模不大或建立之初,一般选择组建全技能普通座席作为生产运营的主力,可称之为“正兵”。

   全技能普通座席的建立可以实现全员识业务、懂系统的运营需求,也可在短时间内调用生产资源,来满足服务资源不足的问题。但随着业务量的增长、服务规模的扩大,多技能普通座席的运营弊端开始显现。
以通信运营商的客户联络中心为例,多技能普通座席存在的弊端如下:

   1、业务量增长迅速,人员需掌握的知识内容多:电信运营商业务种类量级都有数百个或上千个,每个业务再细分不同的知识点,需要上万个文档进行汇编。如果采用复合型普通座席承接,人员需掌握的知识数量过于庞大,因而很难精通全部业务内容,无法成为万能的“专家”。

   2、团队流失率较高,人员职业素质良莠不齐:一般呼叫中心话务员平均流失率在3%-5%,年流失率在20%-30%之间,如果不考虑业务萎缩或新增情况,人员流失后需要补充新的资源进来,而一名新员工从入职到熟练过程需要6个月到12月时间,由于“生手”的存在一定会导致客户的服务感知存在偏差。
  
   3、客户需求呈多样化,快速响应要求高:现在客户需求明显呈多层次化,他们开始关注品质服务、尊享服务、增值服务、延伸服务等精神上的需求,普通座席由于服务对象较多,即使目前已经可以实现大数据标签筛选,再通过弹窗方式识别客户,但很难在技能上完全匹配客户需求,或服务成效不明显。

   此时,就如同用兵作战,我们需要用奇兵取胜,组建一支装备精良的突击队伍(专席),为新形势下产生的新问题或新产品提供服务,进而解决多技能普通座席所面临的“不专”问题。

  首先,我们在组建专席后,可以通过人员集中培训、问题集中反馈推进,快速打造作战队伍,在其作战(服务)方式成熟顺畅后,通过经验模板的沉淀,再传递给作战的主力军即普通座席,进而形成有效的服务配合体系。

 

当然,专席的建立因需要有独立的生产资源,会对客户联络中心的整体运营产生一定的资源耗损,但笔者认为,如果专席的建立能有效支持公司核心战略业务发展或重要客户保障工作,提供更专业更优质的服务,那搭建专席就是有价值且值得投入资源运营的。专席的核心价值,在于集中精力快速解决客户问题,我们称之为运营策略中的“奇兵”,但是,正奇是会随着时间推演而发生变化,比如专席数量越来越庞大,后面会再做进一步的阐述。

   其次,要打造具备有战斗力的奇兵,不是简单的圈一堆人就可以了,需要在业务界定、运作流程、人员选拔等方面进行思考,以便更好的支撑专席运作。

1、圈业务:专席承接业务内容的圈定,首先要考虑公司内外部环境的变化情况,内部环境需要考虑公司战略发展方向,外部环境需要考虑市场竞争形势及客户需求的变化;其次要从业务角度考虑,优先解决复杂、长流程或客户群体较重要的业务。另外,在业务圈定的过程中,需确保被筛选的话务类型便于识别,进而降低一线识别难度及客户的入线门槛。

2、定流程:武器装备是发挥作战效能的关键,专席需要在具备常规装备的基础上,同时具备更为精良、丰富的作战武器。具体在运营上可体现为以下三个方面:其一,专席人员使用的支撑系统及人员操作权限上需更加完备,用于支撑人员解决普席无法解决的各类疑难杂症;其二,专席需与业务管理等后台部门建立更为完善、顺畅的跨部门沟通流程,以便高效开展各类服务运营工作;其三,专席需具备更加丰富、有力的客户声音传递渠道,便于有效解决客户反馈的业务服务短板。

3、选专人:专席承接的是业务难度大、客户咨询细致的高端业务,要求专席代表具备较强的业务素质和学习能力,因此专席代表的选拔不建议采用新人,而是通过对人员绩效、工作年限、实操能力及对专席兴趣的考量,在多技能普通座席人员中选拔。另外,人员在培养阶段,需要有一套完善的培训体系及认证标准,使之与专席定位高度匹配,让专席成为优秀普席代表晋升的途径之一。

二、专席与普席的衔接关系(奇正之变)

   用兵作战注重的是战略部署的灵活多变,客户联络中心的运营也需要做动态调整,其实专席运营策略也是如此,存在奇正之变。

  以笔者所在的广东移动客户服务中心为例,在专席运营过程中,角色定位也发生了三个阶段的演进。

1、引入阶段,专席为奇

  初级的服务策略1.0时期,专席是作战的奇兵,该时期客户需求量少,服务入口识别方便性、座席配置均处于基础搭建阶段,为了保障客户接入感知,一般会采用多技能普通座席转接专席的方式。如广东移动客户服务中心宽带专席,业务发展初期,客户需求通过10086主服务入口进入,通过在线转接的方式传递给专席,此时普席为服务的第一窗口,而专席就是服务的后备奇兵。

2、成长阶段,专席为正

  随着业务发展,客户需求量逐步增加,专席需要从后台走向前台,成为作战的主力军,由“奇兵”成长为“正兵”,也就进入了专席服务策略2.0时期。此阶段,专席人员服务流程较为顺畅、各类运营策略趋于成熟、服务经验也在逐步沉淀,专席处于飞速成长时期。还是以广东移动宽带专席为例,在服务提升时期,我们建立了移动光宽带服务热线1008616,并在10086主渠道下增加宽带服务入口,通过IVR服务策略的配置,实现全量宽带需求直接进入专席,成为面向客户提供服务的第一窗口。

3、成熟阶段,奇正之和

   当业务进入成熟期后,专席数量越来越庞大,由于规模过大出现专席投入资源不足或知识点不断扩大的问题,也就意味着,此时专席充当主力的作战(服务)模式需要做进一步调整,专席服务策略将进入精耕细作的3.0时期,即专席与普席为奇正之和的协同作战(服务)模式。

   当客户拨打服务热线时,通过IVR入线策略将客户的需求进行第一层的辨别,简单服务需求通过路由配置进入普通座席,更高服务技能的复杂服务需求(如故障处理、投诉等)则进入专家专席。同时如普通座席客服代表在服务过程中遇到无法解决的问题,可在线转接至专家座席,由专家团队给予支撑。
QQ图片20170119152935.png

席服务策略演进的三个阶段

   当然,做好专席与普席的衔接,除了有精准客户识别能力以外,重点要打通专席与普席话务转接功能,可查看双方资源闲置状态,避免转接失败和等待给客户带来的不良感知。在话务协同方面,需要在业务管理、投诉管理、营销管理、系统支撑、业务流程优化等方面有明确的协同规范,以更好的支持两种运营模式的衔接。

   综合所述,我们可以看到单技能专席与多技能普通座席的策略选择问题,其实是一个不断变化调整的过程,是所有客户联络中心需要注重运营的动态平衡问题,也是兵法所说的“诡”,即能根据实际情况而随时变化。
 
三、未来展望

   笔者认为,专席的建立,肩负的不仅仅是普通座席的职能,更应该向着“更专业、更优质、更标杆”的目标前进。

   随着人工智能技术的兴起,未来客户联络中心不但是人工专席与普席之间的策略选择问题,更多是在于前端智能机器人与后端人工服务的区别方式,但智能机器人方式解决更多是原有普通座席简单可以处理的问题,相信在未来,对于人工专席的要求会更高,如何让人工价值更加显性,需要我们更多的关注和研究。

本文刊载于《客户世界》2016年12月刊文章;原文作者李俊凡、李雪梅,本文作者单位为中国移动广东公司 客户服务(佛山)中心。 收起阅读 »

Android V2.3.4 已发布,客户端支持修改群描述

5815.jpg_wh860_-_副本_.jpg

Android​ 版本:V2.3.4 2017-1-12

新功能/改进:
  • 增加修改群描述方法EMGroupManager::changeGroupDescription()
  • EMChat::setServerAddress()方法支持设置https地址
  • EMContactManager增加addContactListener(EMContactListener contactListener)方法,方便app在不同类里监听好友变动


Bug Fix:
  • 修复REST短时间内发多条相同内容的消息,客户端只显示一条的bug
  • 修复搜索有时候返回结果不对的bug
  • 修复上个版本出现的个别情况下堆栈溢出的问题

 版本历史:Android 2.X更新日志 
下载地址:SDK下载
继续阅读 »
5815.jpg_wh860_-_副本_.jpg

Android​ 版本:V2.3.4 2017-1-12

新功能/改进:
  • 增加修改群描述方法EMGroupManager::changeGroupDescription()
  • EMChat::setServerAddress()方法支持设置https地址
  • EMContactManager增加addContactListener(EMContactListener contactListener)方法,方便app在不同类里监听好友变动


Bug Fix:
  • 修复REST短时间内发多条相同内容的消息,客户端只显示一条的bug
  • 修复搜索有时候返回结果不对的bug
  • 修复上个版本出现的个别情况下堆栈溢出的问题

 版本历史:Android 2.X更新日志 
下载地址:SDK下载
收起阅读 »

环信移动客服v5.7已发布-十余项更新,更丰富的统计和报表

客服模式

支持客服查看自己的统计数据

客服模式下,新增“统计数据”页面,显示当前客服的核心统计数据,包含接起会话数、结束会话数、平均响应时间、平均首次响应时间、满意度评价、消息/会话数趋势。并支持按日期进行筛选。

选择“统计查询”页面即可查看。统计指标解释如下:
  • 接起会话数:该客服参与的呼入和回呼会话数量总和,包括已结束和进行中会话。
  • 结束会话数:该客服参与的会话中,由该客服结束的会话数量总和。
  • 平均响应时间:该客服参与会话过程中,所有响应时间的平均值。
  • 平均首次响应时间:该客服参与会话过程中,所有首次响应时间的平均值。
  • 满意度评价:该客服参与的会话获得的满意度评价的平均值。如果某条会话经过转接,所有参与客服共享该会话的满意度评价。
  • 消息/会话数趋势:该客服参与会话过程中,每天的消息数和会话数趋势。会话数:该客服的接起会话数;消息数:该客服参与会话期间,客服、访客、系统消息数总和。如果客服A将会话转接给客服B,转接前的消息数属于客服A;转接后的消息数属于客服B。

001.png

【优化】输入框支持Shift+Enter发送消息

“会话”页面的输入框支持选择使用Enter或Shift+Enter发送消息。
002.png

【优化】进行中会话列表显示消息发送失败提示

当客服的消息发送失败时,在原有的消息前提示的基础上,增加进行中会话列表的提示。
003.png

【优化】实时更新客服同事的在线状态

“会话”页面的客服同事列表实时更新客服同事的状态,使内部沟通更方便。

【优化】支持播放移动端客服工作台发送的语音消息

在移动端客服工作台发送的语音消息,支持在web版客服工作台进行播放。

【优化】客服可以看到所接待客户的满意度评价

客服可以在“客户中心”的互动记录中查看所接待客户的满意度评价。
 
 
管理员模式

工作量报表优化,区分客服的工作量数据,新增技能组的工作量数据

优化工作量报表,在原有的会话维度的基础上,增加以客服和技能组为维度的工作量数据统计。如果会话发生了转接,不同客服之间不再共享会话数和消息数。

如下图所示,会话创建后,首先被客服A接入,之后转接给客服B,该会话的指标为:
  • 会话时长:系统的会话时长为,会话接入至会话结束之间的时长;客服A的会话时长为,会话接入至会话转出之间的时长;客服B的会话时长为,会话转入至会话结束之间的时长。
  • 消息数:系统的消息数为,会话开始到结束期间,客服、访客、系统消息数量之和;客服A的消息数为,会话转出之前,客服A、访客、系统消息数量之和;客服B的消息数为,会话转出之后,客服B、访客、系统消息数量之和。


如果一条会话在不同技能组之间转接,技能组的指标和客服的指标算法相似。

前提条件:管理员在“设置”页面开启了“客服可以使用访客中心功能”。
004.png

优化工作量筛选项

支持按照渠道、关联、客服、技能组对工作量数据进行筛选,并且,支持同时选择多个客服或技能组,方便管理员进行数据查询和分类。

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,可以对工作量数据进行筛选。

客服的工作量详情

在管理员模式下,选择“统计查询 > 工作量”,可以直接查看客服的工作量详情数据。优化后的报表对客服的以下指标进行了调整:
  • 接入/转入会话数:该客服接起会话的方式,分为第一次接入的会话数和接起的转入会话数。
  • 转出/结束会话数:该客服完成会话的方式,分为转出的会话数和结束的会话数。
  • 客服/访客/系统消息数:该客服参与会话期间(会话转出前/转出后),客服、访客、系统分别的消息数。
  • 会话时长:该客服参与会话的时长,包括以下几种情况:

  1. 会话接入至结束之间的时长(无转接)
  2. 会话接入至转出之间的时长(有转接)
  3. 会话转入至转出之间的时长(有转接)
  4. 会话转入至结束之间的时长(有转接)

 
  • 单会话消息数:会话过程中,属于该客服的消息条目数量,包含客服、访客、系统消息。
    005.png

技能组的工作量详情

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,选择“技能组”,可以查看技能组的工作量详情数据。技能组的指标算法和客服的指标算法类似,仅举例说明:
  • 接入/转入会话数:该技能组的客服接起会话的方式,分为第一次接入的会话数和收到的转入会话数。
  • 转出/结束会话数:该技能组完成会话的方式,分为转出的会话数和结束的会话数。


注意:如果一条会话在技能组内转接,统计会话数时会去重,只计算一次。 
006.png

工作质量报表优化,区分客服的工作质量数据,新增技能组的工作质量数据

优化工作质量报表,在原有的会话维度的基础上,增加以客服和技能组为维度的工作质量数据统计。如果会话发生了转接,不同客服之间不再共享首次响应时长和响应时长。

如下图所示,会话首先被客服A接入,之后转接给客服B,该会话的指标为:
  • 首次响应时长:系统的首次响应时长为,客服首次回复消息的时间减去会话接入时间;客服A的首次响应时长为,客服A首次回复消息的时间减去会话接入时间;客服B的首次响应时长为,客服B首次回复消息的时间减去会话转入时间。
  • 响应时长:系统的响应时长为,所有客服的响应时间的平均值;客服A的响应时长为,客服A的所有响应时间的平均值;客服B的响应时长为,客服B的所有响应时间的平均值。


如果一条会话在不同技能组之间转接,技能组的指标和客服的指标算法相似。
007.png

优化工作质量筛选项

支持按照渠道、关联、客服、技能组对工作质量数据进行筛选,并且,支持同时选择多个客服或技能组,方便管理员进行数据查询和分类。

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,可以对工作量数据进行筛选。

客服的工作质量详情

在管理员模式下,选择“统计查询 > 工作质量”,可以直接查看客服的工作质量详情数据。优化后的报表对客服的以下指标进行了调整:

首次响应时长:该客服接起会话后,客服的首条人工消息时间减去接起(接入/转入)时间。
响应时长:该客服参与会话期间,多次响应时间的平均值。
008.png

技能组的工作质量详情

在管理员模式下,选择“统计查询 > 工作质量”,点击“筛选排序”,选择“技能组”,可以查看技能组的工作质量详情数据。

技能组的指标算法和客服的指标算法类似,仅举例说明:
  • 首次响应时长:该技能组的客服接起会话后,首条人工客服消息时间减去接起(接入/转入)时间。
  • 响应时长:该技能组参与会话期间,多次响应时间的平均值。


注意:如果一条会话在技能组内转接,统计首次响应时长时,计算多次接入的首次响应时长平均值。
009.png

新增客服工作时长统计

新增“客服时长统计”页面,支持根据日期和时间、客服昵称查看客服的在线(空闲、忙碌、隐身、离开)和离线时长,并导出客服状态详情。显示的在线和离线时长总和为选择的时间段的长度。

点击任意一名客服的记录,可以查看该客服的登录详情,包含每次登录使用的IP地址。
010.png

新增排队次数分布

在“排队统计”页面,新增按会话标签维度的排队次数分布,展示不同会话标签的会话曾经在客服系统中的排队次数,便于定位不同类型的会话的排队情况。
011.png

精确统计技能组数据

新增“精确统计技能组数据”开关,开关打开时,会话转接页面调整为以技能组分类的窗格,可以将会话转接给技能组或技能组下的客服,保证技能组数据统计更精准。 如果您需要更准确的技能组数据,可以进入管理员模式,选择“设置 > 系统开关”,打开此开关。
012.png

计算客服当前会话工作台显示的时长,最后一条消息可以是访客或客服

新增开关“计算客服当前会话工作台显示的时长,最后一条消息可以是访客或客服”。该开关默认关闭。关闭时,进行中会话列表显示访客最后一次发送消息的时间与当前时间的差异;开关打开时,显示访客或客服最后一条消息的时间与当前时间的差异。

如果您希望改变进行中会话列表的时间显示方式,可以进入管理员模式,选择“设置 > 系统开关”,打开此开关。
013.png

客服维度的会话质检

优化“质量检查”功能,将基于会话的质检更改为基于客服的质检。

质量检查页面的列表显示参与会话的每位客服的首次响应时长、会话时长、平均响应时长这些指标,以及会话整体的满意度评价指标。质检员可以基于每位客服参与会话期间的表现分别给予评分。
014.png

搜索、历史会话快速质检

为了满足不同场景下的会话质检需求,新增多入口快速质检功能,在管理员模式的“搜索”和“历史会话”页面均可以对会话进行快速质检。

以“历史会话”为例,点击一条历史会话,进入该会话的详情页。点击“质检”页签,可以查看该会话的首次响应时长、会话时长、平均响应时长、满意度评价这些指标。如果会话经过转接,可以查看经手的每位客服的上述指标。您可以根据历史消息记录和这些指标进行会话的快速质检。
015.png

【优化】管理技能组成员时,支持搜索当前成员

在“成员管理 > 技能组”页面,管理技能组成员时,支持对当前成员进行搜索,快速定位客服。

【优化】APP关联支持使用“商城”demo扫码

APP关联的详情页新增二维码,使用手机扫码工具扫描并在浏览器打开后,可以下载新版“商城”demo,而使用新版“商城”demo扫码时,将自动配置租户ID、IM服务号等信息,无需手动填写。

之后,可以用“商城”demo向客服发起聊天或留言,测试移动客服的会话和留言功能。

【优化】支持导出机器人的知识规则

支持导出机器人的知识规则,导出后,可以在本地编辑并重新导入,方便批量整理知识规则。

进入“智能机器人 > 机器人设置 > 知识规则”页签,点击“导出知识规则”按钮,即可导出全部知识规则。

【优化】客户之声支持导出关键词的消息详情

在“客户之声”页面,查看关键词的相关消息列表时,可以点击任意一条会话,进入详情页,导出该条会话的消息内容。导出文件可在“导出管理”页面进行下载。

“客户之声”功能为增值服务,请联系环信商务经理开通哦。
 
Web访客端

支持Web端客户发送文件

环信移动客服的web插件支持发送文件,客户使用PC聊天窗口和H5网页联系客服时,均可以向客服发送文件。客服在客服工作台收到文件后,可以下载到本地进行查看。

该功能属于Webim plugin V43.12,如果您正在使用定制开发版,请更新到最新版本。

多租户管理后台

多租户管理后台进一步完善了租户的统计数据。

支持查看、筛选、并导出所有租户的统计数据

在多租户管理后台,可以查看平台下所有租户的统计数据,支持按照租户ID、日期、会话时长平均值、首次响应时长平均值、响应时长平均值、满意度评价对租户进行筛选以及质检,并导出筛选结果。

进入“统计”页面,可以查看、筛选、导出这些统计数据。在页面内进行左右滑动,以查看更多项目。
016.png

在“导出管理”页面,可以下载导出文件。
017.png

支持查看单个租户的当前会话列表及消息内容

在“租户管理”页面,选择某个租户,在租户详情页点击“当前会话”,可以查看该租户的当前会话列表。点击任意一条会话,可以查看该会话的消息详情。
018.png

 
环信移动客服更新日志http://docs.easemob.com/cs/releasenote/5.7
 
环信移动客服登陆地址http://kefu.easemob.com/
继续阅读 »
客服模式

支持客服查看自己的统计数据

客服模式下,新增“统计数据”页面,显示当前客服的核心统计数据,包含接起会话数、结束会话数、平均响应时间、平均首次响应时间、满意度评价、消息/会话数趋势。并支持按日期进行筛选。

选择“统计查询”页面即可查看。统计指标解释如下:
  • 接起会话数:该客服参与的呼入和回呼会话数量总和,包括已结束和进行中会话。
  • 结束会话数:该客服参与的会话中,由该客服结束的会话数量总和。
  • 平均响应时间:该客服参与会话过程中,所有响应时间的平均值。
  • 平均首次响应时间:该客服参与会话过程中,所有首次响应时间的平均值。
  • 满意度评价:该客服参与的会话获得的满意度评价的平均值。如果某条会话经过转接,所有参与客服共享该会话的满意度评价。
  • 消息/会话数趋势:该客服参与会话过程中,每天的消息数和会话数趋势。会话数:该客服的接起会话数;消息数:该客服参与会话期间,客服、访客、系统消息数总和。如果客服A将会话转接给客服B,转接前的消息数属于客服A;转接后的消息数属于客服B。

001.png

【优化】输入框支持Shift+Enter发送消息

“会话”页面的输入框支持选择使用Enter或Shift+Enter发送消息。
002.png

【优化】进行中会话列表显示消息发送失败提示

当客服的消息发送失败时,在原有的消息前提示的基础上,增加进行中会话列表的提示。
003.png

【优化】实时更新客服同事的在线状态

“会话”页面的客服同事列表实时更新客服同事的状态,使内部沟通更方便。

【优化】支持播放移动端客服工作台发送的语音消息

在移动端客服工作台发送的语音消息,支持在web版客服工作台进行播放。

【优化】客服可以看到所接待客户的满意度评价

客服可以在“客户中心”的互动记录中查看所接待客户的满意度评价。
 
 
管理员模式

工作量报表优化,区分客服的工作量数据,新增技能组的工作量数据

优化工作量报表,在原有的会话维度的基础上,增加以客服和技能组为维度的工作量数据统计。如果会话发生了转接,不同客服之间不再共享会话数和消息数。

如下图所示,会话创建后,首先被客服A接入,之后转接给客服B,该会话的指标为:
  • 会话时长:系统的会话时长为,会话接入至会话结束之间的时长;客服A的会话时长为,会话接入至会话转出之间的时长;客服B的会话时长为,会话转入至会话结束之间的时长。
  • 消息数:系统的消息数为,会话开始到结束期间,客服、访客、系统消息数量之和;客服A的消息数为,会话转出之前,客服A、访客、系统消息数量之和;客服B的消息数为,会话转出之后,客服B、访客、系统消息数量之和。


如果一条会话在不同技能组之间转接,技能组的指标和客服的指标算法相似。

前提条件:管理员在“设置”页面开启了“客服可以使用访客中心功能”。
004.png

优化工作量筛选项

支持按照渠道、关联、客服、技能组对工作量数据进行筛选,并且,支持同时选择多个客服或技能组,方便管理员进行数据查询和分类。

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,可以对工作量数据进行筛选。

客服的工作量详情

在管理员模式下,选择“统计查询 > 工作量”,可以直接查看客服的工作量详情数据。优化后的报表对客服的以下指标进行了调整:
  • 接入/转入会话数:该客服接起会话的方式,分为第一次接入的会话数和接起的转入会话数。
  • 转出/结束会话数:该客服完成会话的方式,分为转出的会话数和结束的会话数。
  • 客服/访客/系统消息数:该客服参与会话期间(会话转出前/转出后),客服、访客、系统分别的消息数。
  • 会话时长:该客服参与会话的时长,包括以下几种情况:

  1. 会话接入至结束之间的时长(无转接)
  2. 会话接入至转出之间的时长(有转接)
  3. 会话转入至转出之间的时长(有转接)
  4. 会话转入至结束之间的时长(有转接)

 
  • 单会话消息数:会话过程中,属于该客服的消息条目数量,包含客服、访客、系统消息。
    005.png

技能组的工作量详情

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,选择“技能组”,可以查看技能组的工作量详情数据。技能组的指标算法和客服的指标算法类似,仅举例说明:
  • 接入/转入会话数:该技能组的客服接起会话的方式,分为第一次接入的会话数和收到的转入会话数。
  • 转出/结束会话数:该技能组完成会话的方式,分为转出的会话数和结束的会话数。


注意:如果一条会话在技能组内转接,统计会话数时会去重,只计算一次。 
006.png

工作质量报表优化,区分客服的工作质量数据,新增技能组的工作质量数据

优化工作质量报表,在原有的会话维度的基础上,增加以客服和技能组为维度的工作质量数据统计。如果会话发生了转接,不同客服之间不再共享首次响应时长和响应时长。

如下图所示,会话首先被客服A接入,之后转接给客服B,该会话的指标为:
  • 首次响应时长:系统的首次响应时长为,客服首次回复消息的时间减去会话接入时间;客服A的首次响应时长为,客服A首次回复消息的时间减去会话接入时间;客服B的首次响应时长为,客服B首次回复消息的时间减去会话转入时间。
  • 响应时长:系统的响应时长为,所有客服的响应时间的平均值;客服A的响应时长为,客服A的所有响应时间的平均值;客服B的响应时长为,客服B的所有响应时间的平均值。


如果一条会话在不同技能组之间转接,技能组的指标和客服的指标算法相似。
007.png

优化工作质量筛选项

支持按照渠道、关联、客服、技能组对工作质量数据进行筛选,并且,支持同时选择多个客服或技能组,方便管理员进行数据查询和分类。

在管理员模式下,选择“统计查询 > 工作量”,点击“筛选排序”,可以对工作量数据进行筛选。

客服的工作质量详情

在管理员模式下,选择“统计查询 > 工作质量”,可以直接查看客服的工作质量详情数据。优化后的报表对客服的以下指标进行了调整:

首次响应时长:该客服接起会话后,客服的首条人工消息时间减去接起(接入/转入)时间。
响应时长:该客服参与会话期间,多次响应时间的平均值。
008.png

技能组的工作质量详情

在管理员模式下,选择“统计查询 > 工作质量”,点击“筛选排序”,选择“技能组”,可以查看技能组的工作质量详情数据。

技能组的指标算法和客服的指标算法类似,仅举例说明:
  • 首次响应时长:该技能组的客服接起会话后,首条人工客服消息时间减去接起(接入/转入)时间。
  • 响应时长:该技能组参与会话期间,多次响应时间的平均值。


注意:如果一条会话在技能组内转接,统计首次响应时长时,计算多次接入的首次响应时长平均值。
009.png

新增客服工作时长统计

新增“客服时长统计”页面,支持根据日期和时间、客服昵称查看客服的在线(空闲、忙碌、隐身、离开)和离线时长,并导出客服状态详情。显示的在线和离线时长总和为选择的时间段的长度。

点击任意一名客服的记录,可以查看该客服的登录详情,包含每次登录使用的IP地址。
010.png

新增排队次数分布

在“排队统计”页面,新增按会话标签维度的排队次数分布,展示不同会话标签的会话曾经在客服系统中的排队次数,便于定位不同类型的会话的排队情况。
011.png

精确统计技能组数据

新增“精确统计技能组数据”开关,开关打开时,会话转接页面调整为以技能组分类的窗格,可以将会话转接给技能组或技能组下的客服,保证技能组数据统计更精准。 如果您需要更准确的技能组数据,可以进入管理员模式,选择“设置 > 系统开关”,打开此开关。
012.png

计算客服当前会话工作台显示的时长,最后一条消息可以是访客或客服

新增开关“计算客服当前会话工作台显示的时长,最后一条消息可以是访客或客服”。该开关默认关闭。关闭时,进行中会话列表显示访客最后一次发送消息的时间与当前时间的差异;开关打开时,显示访客或客服最后一条消息的时间与当前时间的差异。

如果您希望改变进行中会话列表的时间显示方式,可以进入管理员模式,选择“设置 > 系统开关”,打开此开关。
013.png

客服维度的会话质检

优化“质量检查”功能,将基于会话的质检更改为基于客服的质检。

质量检查页面的列表显示参与会话的每位客服的首次响应时长、会话时长、平均响应时长这些指标,以及会话整体的满意度评价指标。质检员可以基于每位客服参与会话期间的表现分别给予评分。
014.png

搜索、历史会话快速质检

为了满足不同场景下的会话质检需求,新增多入口快速质检功能,在管理员模式的“搜索”和“历史会话”页面均可以对会话进行快速质检。

以“历史会话”为例,点击一条历史会话,进入该会话的详情页。点击“质检”页签,可以查看该会话的首次响应时长、会话时长、平均响应时长、满意度评价这些指标。如果会话经过转接,可以查看经手的每位客服的上述指标。您可以根据历史消息记录和这些指标进行会话的快速质检。
015.png

【优化】管理技能组成员时,支持搜索当前成员

在“成员管理 > 技能组”页面,管理技能组成员时,支持对当前成员进行搜索,快速定位客服。

【优化】APP关联支持使用“商城”demo扫码

APP关联的详情页新增二维码,使用手机扫码工具扫描并在浏览器打开后,可以下载新版“商城”demo,而使用新版“商城”demo扫码时,将自动配置租户ID、IM服务号等信息,无需手动填写。

之后,可以用“商城”demo向客服发起聊天或留言,测试移动客服的会话和留言功能。

【优化】支持导出机器人的知识规则

支持导出机器人的知识规则,导出后,可以在本地编辑并重新导入,方便批量整理知识规则。

进入“智能机器人 > 机器人设置 > 知识规则”页签,点击“导出知识规则”按钮,即可导出全部知识规则。

【优化】客户之声支持导出关键词的消息详情

在“客户之声”页面,查看关键词的相关消息列表时,可以点击任意一条会话,进入详情页,导出该条会话的消息内容。导出文件可在“导出管理”页面进行下载。

“客户之声”功能为增值服务,请联系环信商务经理开通哦。
 
Web访客端

支持Web端客户发送文件

环信移动客服的web插件支持发送文件,客户使用PC聊天窗口和H5网页联系客服时,均可以向客服发送文件。客服在客服工作台收到文件后,可以下载到本地进行查看。

该功能属于Webim plugin V43.12,如果您正在使用定制开发版,请更新到最新版本。

多租户管理后台

多租户管理后台进一步完善了租户的统计数据。

支持查看、筛选、并导出所有租户的统计数据

在多租户管理后台,可以查看平台下所有租户的统计数据,支持按照租户ID、日期、会话时长平均值、首次响应时长平均值、响应时长平均值、满意度评价对租户进行筛选以及质检,并导出筛选结果。

进入“统计”页面,可以查看、筛选、导出这些统计数据。在页面内进行左右滑动,以查看更多项目。
016.png

在“导出管理”页面,可以下载导出文件。
017.png

支持查看单个租户的当前会话列表及消息内容

在“租户管理”页面,选择某个租户,在租户详情页点击“当前会话”,可以查看该租户的当前会话列表。点击任意一条会话,可以查看该会话的消息详情。
018.png

 
环信移动客服更新日志http://docs.easemob.com/cs/releasenote/5.7
 
环信移动客服登陆地址http://kefu.easemob.com/
收起阅读 »

环信及时通信iOS SDK的一些看法和建议

先说下环境:我使用的是HyphenateLite,3.2.3版本
 1,关于bitcode
终于看到3.2.3版本有说:sdk支持bitcode拉,赶紧下载组装。编译时提示:
libopencore-amrnb.a(wrapper.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
看来官方给出的sdk支持bitcode还真是仅限于“sdk”了,EaseUI里的libopencore-amrnb不是环信出品的,就不管了??可这对开发者来说有什么用呢?我们需要sdk提供的全部组件都支持bicode才行呢!!!
另外:跟iOS SDK客服沟通了下,似乎没有搞明白开启bitcode时什么意思。
强调一遍:必须在TARGET中设置bitcode为YES,然后真机运行,真机运行!!!!
麻烦官方再仔细检查一遍给我们开发者一个真正能用的bitcode版本!!!
 
2,关于文档
这次3.2.3说使用了动态framework,嗯,对官方的这种与时俱进赞一个。但你们能仔细看看给的文档吗:

注: 由于 iOS 编译的特殊性,为了方便开发者使用,我们将 i386 x86_64 armv7 arm64 几个平台都合并到了一起,所以使用动态库上传appstore时需要将i386 x86_64两个平台删除后,才能正常提交


然后呢?如何操作?能再简洁一点吗?
熟悉开发的肯定都知道用lipo操作,但是刚入门的是还需要查询的呀。能直接说下怎么操作岂不是更好!
 
3,一些建议
1,做SDK不像平常开发个app,自己的一亩三分地想怎么搞就怎么搞,sdk是拿出来给大家用的,对象都是开发者,需要开发sdk的同学本身就非常精通。一个建议,对于暴漏的.h文件最好都引用:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>//如何有UI
 
2,并且文档什么的要尽量细化。看到官方推出了不少视频的开发文档,这个虽然很好,降低了门槛,可是sdk总是在升级的在变动的,视频的内容往往发出来不久就落后于实际的代码了。建议多些文字文档,重要步骤尽量详细,文字能快速传达信息,没人有希望集成个sdk都要花费很多时间。
 
以上是我个人的浅见,不是纯粹是发牢骚,大家都是开发者,都希望作品精益求精,希望共同进步!
 
匆促中难免有错字,望理解!谢谢!
 
继续阅读 »
先说下环境:我使用的是HyphenateLite,3.2.3版本
 1,关于bitcode
终于看到3.2.3版本有说:sdk支持bitcode拉,赶紧下载组装。编译时提示:
libopencore-amrnb.a(wrapper.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
看来官方给出的sdk支持bitcode还真是仅限于“sdk”了,EaseUI里的libopencore-amrnb不是环信出品的,就不管了??可这对开发者来说有什么用呢?我们需要sdk提供的全部组件都支持bicode才行呢!!!
另外:跟iOS SDK客服沟通了下,似乎没有搞明白开启bitcode时什么意思。
强调一遍:必须在TARGET中设置bitcode为YES,然后真机运行,真机运行!!!!
麻烦官方再仔细检查一遍给我们开发者一个真正能用的bitcode版本!!!
 
2,关于文档
这次3.2.3说使用了动态framework,嗯,对官方的这种与时俱进赞一个。但你们能仔细看看给的文档吗:

注: 由于 iOS 编译的特殊性,为了方便开发者使用,我们将 i386 x86_64 armv7 arm64 几个平台都合并到了一起,所以使用动态库上传appstore时需要将i386 x86_64两个平台删除后,才能正常提交


然后呢?如何操作?能再简洁一点吗?
熟悉开发的肯定都知道用lipo操作,但是刚入门的是还需要查询的呀。能直接说下怎么操作岂不是更好!
 
3,一些建议
1,做SDK不像平常开发个app,自己的一亩三分地想怎么搞就怎么搞,sdk是拿出来给大家用的,对象都是开发者,需要开发sdk的同学本身就非常精通。一个建议,对于暴漏的.h文件最好都引用:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>//如何有UI
 
2,并且文档什么的要尽量细化。看到官方推出了不少视频的开发文档,这个虽然很好,降低了门槛,可是sdk总是在升级的在变动的,视频的内容往往发出来不久就落后于实际的代码了。建议多些文字文档,重要步骤尽量详细,文字能快速传达信息,没人有希望集成个sdk都要花费很多时间。
 
以上是我个人的浅见,不是纯粹是发牢骚,大家都是开发者,都希望作品精益求精,希望共同进步!
 
匆促中难免有错字,望理解!谢谢!
  收起阅读 »

项目整合环信中遇到的问题

    在项目开发过程中,有聊天社区的需求,经过研究后,最终选择环信,因为环信的服务真的很不错,无论是技术还是服务,都很到位,客服人员和技术人员都会耐心地解答开发中遇到的问题,只不过在开发的过程中发现demo中的有些代码并未及时更新,并且部分接口功能有些限制,不过还是由衷的感谢,希望环信发展越来越好!
    整合过程中遇到的相关问题:
     1、在配置文件中配置在环信中注册app的相关信息,如:API_PROTOCAL、API_HOST、API_ORG、API_APP、APP_CLIENT_ID、APP_CLIENT_SECRET等;
     2、api接口实现类中的发送请求时请求的方法(demo中的代码可能没及时更新)
     3、公共类中的部分body类的get方法(demo中表示的都是同一代码,但实际应用中并不这样)
     4、聊天记录信息需要保存在本地服务器(环信的服务器保存期限是3天)
   
     感恩环信,希望环信早日上市!
    
    
继续阅读 »
    在项目开发过程中,有聊天社区的需求,经过研究后,最终选择环信,因为环信的服务真的很不错,无论是技术还是服务,都很到位,客服人员和技术人员都会耐心地解答开发中遇到的问题,只不过在开发的过程中发现demo中的有些代码并未及时更新,并且部分接口功能有些限制,不过还是由衷的感谢,希望环信发展越来越好!
    整合过程中遇到的相关问题:
     1、在配置文件中配置在环信中注册app的相关信息,如:API_PROTOCAL、API_HOST、API_ORG、API_APP、APP_CLIENT_ID、APP_CLIENT_SECRET等;
     2、api接口实现类中的发送请求时请求的方法(demo中的代码可能没及时更新)
     3、公共类中的部分body类的get方法(demo中表示的都是同一代码,但实际应用中并不这样)
     4、聊天记录信息需要保存在本地服务器(环信的服务器保存期限是3天)
   
     感恩环信,希望环信早日上市!
    
     收起阅读 »

环信Android SDK的些许建议

由于公司应用业务需要集成即时通信框架,对比多方后选择了环信,从应用上线到现在,可以说看着环信一点一点不断的改变完善,从原来的2.x到现在的3.x,功能越来越完善,接口分离封装的越来越好,不过使用过程中还是会碰到一些问题,总结总结提一点建议
1、社区问题讨论不够活跃,大部分碰到的问题在社区中找不到,很多问题没有官方解答,相反QQ群的技术支持反而更好,解决问题很及时,解答也很专业,这里感谢下QQ群的小伙伴们
2、文档不够完善,由于做Android的开发,所以这点仅限于Android文档,文档比起以前要好很多,但是说明还是太过宽泛,一些具体的设置及解决方案还要去demo中寻找,这就相当费时间了
3、上面说到了有些东西要去demo中找,下面就不得不吐槽下Android demo了,真是看到让人头大,一个类中放了一堆的东西,虽然有继承和封装,感觉看着真心累,尤其是当碰到一些问题需要再demo找解决方法的时候,真是生无可恋,感觉现在的demo一直从2.X时代继承过来,只是把新功能添加了进去,没有像SDK一样,重新规划来一版新的demo,相信这个demo也让不少小伙伴心有同感
 
不管怎么说,瑕不掩瑜,环信作为即时通信领域的佼佼者,为广大开发者提供了很多帮助和便捷,希望环信能越来越好,开放给广大开发者的接口或资源越来越多一些,在新的一年里一起加油!!!
继续阅读 »
由于公司应用业务需要集成即时通信框架,对比多方后选择了环信,从应用上线到现在,可以说看着环信一点一点不断的改变完善,从原来的2.x到现在的3.x,功能越来越完善,接口分离封装的越来越好,不过使用过程中还是会碰到一些问题,总结总结提一点建议
1、社区问题讨论不够活跃,大部分碰到的问题在社区中找不到,很多问题没有官方解答,相反QQ群的技术支持反而更好,解决问题很及时,解答也很专业,这里感谢下QQ群的小伙伴们
2、文档不够完善,由于做Android的开发,所以这点仅限于Android文档,文档比起以前要好很多,但是说明还是太过宽泛,一些具体的设置及解决方案还要去demo中寻找,这就相当费时间了
3、上面说到了有些东西要去demo中找,下面就不得不吐槽下Android demo了,真是看到让人头大,一个类中放了一堆的东西,虽然有继承和封装,感觉看着真心累,尤其是当碰到一些问题需要再demo找解决方法的时候,真是生无可恋,感觉现在的demo一直从2.X时代继承过来,只是把新功能添加了进去,没有像SDK一样,重新规划来一版新的demo,相信这个demo也让不少小伙伴心有同感
 
不管怎么说,瑕不掩瑜,环信作为即时通信领域的佼佼者,为广大开发者提供了很多帮助和便捷,希望环信能越来越好,开放给广大开发者的接口或资源越来越多一些,在新的一年里一起加油!!! 收起阅读 »

web应用与环信的故事

web
在为一个大学开发官方网站的时候,有一个OA的需求。
由于时间比较赶,采用了环信的web端。
在开发的过程中直接使用了环信的demo。不得不说,环信的demo做的还是挺好看的。但是接口开放的比较少,而且文档也比较粗糙,然而功能还是够用的。有一个坑是用户需要在本地保存聊天记录,而咨询客服后表示web暂时没有这个接口,因此我们只能在demo里自己写了一套异步传输到数据库,用户通过登陆在数据库查询,希望环信以后能够开放web端的本地存储。
继续阅读 »
在为一个大学开发官方网站的时候,有一个OA的需求。
由于时间比较赶,采用了环信的web端。
在开发的过程中直接使用了环信的demo。不得不说,环信的demo做的还是挺好看的。但是接口开放的比较少,而且文档也比较粗糙,然而功能还是够用的。有一个坑是用户需要在本地保存聊天记录,而咨询客服后表示web暂时没有这个接口,因此我们只能在demo里自己写了一套异步传输到数据库,用户通过登陆在数据库查询,希望环信以后能够开放web端的本地存储。 收起阅读 »

喜大奔普,环信IM Demo登录苹果应用商店!

    
   据环信社报道,环信IM Demo于2017年1月9日正式登录苹果AppStore,意味着小伙伴们可以在AppStore上直接下载到环信最新IM Demo啦。目前在苹果应用商店的版本为最新的IOS3.2.3,未来也将于环信官网同步更新,同时Android的IM demo也陆续上传到各大应用市场,方便小伙伴们下载使用,大家在使用过程中遇到问题可以在imgeek社区(http://www.imgeek.org) 反馈,我们将第一时间处理。

442371770580111367.png

环信IM Demo登录苹果应用商店


   环信即时通讯云作为国内最早也是全球最大的即时通讯云PaaS平台,为开发者提供基于移动互联网的即时通讯能力,如单聊、群聊、发语音、发图片、发位置、实时音频、实时视频等,让开发者摆脱繁重的移动IM通讯底层开发,24小时即可让App拥有内置IM能力,帮助APP轻松实现社交功能。近期也上线了包括环信红包、环信直播等明星产品,深受开发者喜爱。

   截至2016年上半年,环信共服务了82149家App客户,SDK覆盖手机终端5.64亿,平台日发送消息5.57亿条。典型用户包括快牙、国美在线、猎聘同道、百合相亲、宝宝树、迪信通等。

本次上线苹果AppStore的环信IM Demo展示了如何使用环信SDK创建一个完整的即时通讯APP,主要功能包括:用户注册和登录,好友管理,单聊/群聊,支持包括文字、表情、语音、图片、地理位置等消息类型,用户也可以通过Demo进行实时音视频通话等。
继续阅读 »
    
   据环信社报道,环信IM Demo于2017年1月9日正式登录苹果AppStore,意味着小伙伴们可以在AppStore上直接下载到环信最新IM Demo啦。目前在苹果应用商店的版本为最新的IOS3.2.3,未来也将于环信官网同步更新,同时Android的IM demo也陆续上传到各大应用市场,方便小伙伴们下载使用,大家在使用过程中遇到问题可以在imgeek社区(http://www.imgeek.org) 反馈,我们将第一时间处理。

442371770580111367.png

环信IM Demo登录苹果应用商店


   环信即时通讯云作为国内最早也是全球最大的即时通讯云PaaS平台,为开发者提供基于移动互联网的即时通讯能力,如单聊、群聊、发语音、发图片、发位置、实时音频、实时视频等,让开发者摆脱繁重的移动IM通讯底层开发,24小时即可让App拥有内置IM能力,帮助APP轻松实现社交功能。近期也上线了包括环信红包、环信直播等明星产品,深受开发者喜爱。

   截至2016年上半年,环信共服务了82149家App客户,SDK覆盖手机终端5.64亿,平台日发送消息5.57亿条。典型用户包括快牙、国美在线、猎聘同道、百合相亲、宝宝树、迪信通等。

本次上线苹果AppStore的环信IM Demo展示了如何使用环信SDK创建一个完整的即时通讯APP,主要功能包括:用户注册和登录,好友管理,单聊/群聊,支持包括文字、表情、语音、图片、地理位置等消息类型,用户也可以通过Demo进行实时音视频通话等。 收起阅读 »

我要上周刊!欢迎推荐内容到技术周刊!


如果你发现了好内容希望分享更多的朋友们,
如果你觉得你的文章很赞需要推送,欢迎联系我们......
历史技术周报合集:http://www.easemob.com/weekly 
技术周报是精选了一周的优质内容的集合,欢迎各位按照如下格式推荐精品内容:
1. 推荐内容:标题
2. 推荐链接:XXX
3. 推荐理由:XXXXX
继续阅读 »

如果你发现了好内容希望分享更多的朋友们,
如果你觉得你的文章很赞需要推送,欢迎联系我们......
历史技术周报合集:http://www.easemob.com/weekly 
技术周报是精选了一周的优质内容的集合,欢迎各位按照如下格式推荐精品内容:
1. 推荐内容:标题
2. 推荐链接:XXX
3. 推荐理由:XXXXX 收起阅读 »

将环信集成到已有的业务体系,后台用php写的接口

我做的是一个普通资讯类app,需要集成即时通讯,在比较以后,还是选择了环信。
首先讲下版本,开始开始集成环信的应用的时间比较早,用的是2.1.6版本。
后台接口用的php和mysql。
下面,我就将应用本身的注册,登陆和环信的想结合的逻辑分享下。
1.登陆的逻辑是,先在app里面调用服务器接口,接口里面判断账号密码是否正确,(注意:在做环信的登陆的时候,为了安全,我并不是直接使用用户的账号密码登陆,而是用户唯一uid和加密后的密码)。
代码如下:  
  EMChatManager.getInstance().login(username, password,
new EMCallBack() {
#####
});

2.这里要说下关于用户昵称和头像,官方给出了两个解决方案,我选择的就是第一个方案。在登陆成功的回掉里面,you有这样的代码
  try {
// ** 第一次登录或者之前logout后再登录,加载所有本地群和回话
// 处理好友和群组
processContactsAndGroups();
}
我就是在这里去出来头像和昵称的,用sqlite来保存。在保存的时候,异步通过用户list的username去后台请求昵称和头像,然后保存到sqlite。然后再messageAdapter中设置。
MessageAdapter中
/**
* 显示用户头像
*
* @param message
* @param imageView
*/
private void setUserAvatar(EMMessage message, ImageView imageView) {
if (message.direct == Direct.SEND) {
// // 显示自己头像

UserUtils.setSendAvatar(context, imageView);
} else {
UserUtils.setDirectAvatar(context, message, imageView);
}
}

UserUtils内容
/**
* 设置对方头像
*
* @param username
*/
public static void setDirectAvatar(Context context, EMMessage message,
ImageView imageView) {
AppContext appContext = (AppContext) context.getApplicationContext();
HXIMUserDao hximUserDao = appContext.getHXIMUserDao();
String dbface = hximUserDao.viewItem(HXIMUserDao.COLUMN_NAME_NAME
+ "=?", new String { message.getFrom() });
if (dbface != null&&dbface.length()>0) {
Picasso.with(context).load(dbface)
.placeholder(R.drawable.default_avatar).into(imageView);
} else {
IMUser user = getUserInfo(message.getFrom());
Picasso.with(context).load(user.getAvatar())
.placeholder(R.drawable.default_avatar).into(imageView);
}
}

HXIMUserDao内容 
    @Override
public String viewItem(String selection, String selectionArgs) {
SQLiteDatabase database = null;
Cursor cursor = null;
Map<String, String> map = new HashMap<String, String>();

try {
database = hximusersqlhelper.getWritableDatabase();

cursor = database.query(false, TABLE_NAME, null, selection,
selectionArgs, null, null, null, null);
int cols_len = cursor.getColumnCount();
while (cursor.moveToNext()) {
for (int i = 0; i < cols_len; i++) {
String cols_name = cursor.getColumnName(i);
String cols_values = cursor.getString(cursor
.getColumnIndex(cols_name));
if (cols_values == null) {
cols_values = "";
}
map.put(cols_name, cols_values);
}
}

} catch (Exception e) {
// TODO: handle exception
} finally {
if (database != null) {
database.close();
}
}

return map.get(COLUMN_NAME_FACE);

}

3.关于注册,由于环信的提倡的是用REST API 注册,不是在app里面,所以注册接口逻辑是,当用户提交账号 和密码我就在自己的数据库中添加一条记录并且返回uid,然后用uid和经过加密后的密码 去向环信提交注册。
 //$result为0注册失败
//注册成功后再取hx注册 ,成功则返回result为true
//否则返回false同时删除再app服务器上的注册
if ($result) {

$registcondition['user_id']=$result;
$User=$this->model->table('user');
$registinfo=$User->where($registcondition)->find();

$hxoptions['username']=$registinfo['user_id'];
$hxoptions['password']=$registinfo['user_userpass'];

$mooptions['client_id']=$this->config['CLIENT_ID'];
$mooptions['client_secret']=$this->config['CLIENT_SECRET'];
$mooptions['org_name']=$this->config['ORG_NAME'];
$mooptions['app_name']=$this->config['APP_NAME'];

require_once('Easemob.class.php');
$Easemob = new Easemob($mooptions);
$hxregisterresult= $Easemob->accreditRegister($hxoptions);

if ($hxregisterresult['status']==200) {
$result=true;
}else{
$deleteuser['user_id']=$result;
$deleteresult=$User->where($deleteuser)->delete();
$result=false;
}
}

注意,如果在环信上如果注册失败,则要在本地删除这条记录,以免用处再次cha尝试注册的时候 ,提示已经注册,但其实环信没有注册成功所以无法登陆。修改密码也是这样的 。
 
建议:在sdk里面,好像没有将该会话置顶的方法。而是统一按照最后消息排序
 
最后感谢下环信,不管从消息下发,文档,sdk,以及客服各个方面来说都做的不错。最后提交一张我自己集成会话的页面截图。
 
继续阅读 »
我做的是一个普通资讯类app,需要集成即时通讯,在比较以后,还是选择了环信。
首先讲下版本,开始开始集成环信的应用的时间比较早,用的是2.1.6版本。
后台接口用的php和mysql。
下面,我就将应用本身的注册,登陆和环信的想结合的逻辑分享下。
1.登陆的逻辑是,先在app里面调用服务器接口,接口里面判断账号密码是否正确,(注意:在做环信的登陆的时候,为了安全,我并不是直接使用用户的账号密码登陆,而是用户唯一uid和加密后的密码)。
代码如下:  
  EMChatManager.getInstance().login(username, password,
new EMCallBack() {
#####
});

2.这里要说下关于用户昵称和头像,官方给出了两个解决方案,我选择的就是第一个方案。在登陆成功的回掉里面,you有这样的代码
  try {
// ** 第一次登录或者之前logout后再登录,加载所有本地群和回话
// 处理好友和群组
processContactsAndGroups();
}
我就是在这里去出来头像和昵称的,用sqlite来保存。在保存的时候,异步通过用户list的username去后台请求昵称和头像,然后保存到sqlite。然后再messageAdapter中设置。
MessageAdapter中
/**
* 显示用户头像
*
* @param message
* @param imageView
*/
private void setUserAvatar(EMMessage message, ImageView imageView) {
if (message.direct == Direct.SEND) {
// // 显示自己头像

UserUtils.setSendAvatar(context, imageView);
} else {
UserUtils.setDirectAvatar(context, message, imageView);
}
}

UserUtils内容
/**
* 设置对方头像
*
* @param username
*/
public static void setDirectAvatar(Context context, EMMessage message,
ImageView imageView) {
AppContext appContext = (AppContext) context.getApplicationContext();
HXIMUserDao hximUserDao = appContext.getHXIMUserDao();
String dbface = hximUserDao.viewItem(HXIMUserDao.COLUMN_NAME_NAME
+ "=?", new String { message.getFrom() });
if (dbface != null&&dbface.length()>0) {
Picasso.with(context).load(dbface)
.placeholder(R.drawable.default_avatar).into(imageView);
} else {
IMUser user = getUserInfo(message.getFrom());
Picasso.with(context).load(user.getAvatar())
.placeholder(R.drawable.default_avatar).into(imageView);
}
}

HXIMUserDao内容 
    @Override
public String viewItem(String selection, String selectionArgs) {
SQLiteDatabase database = null;
Cursor cursor = null;
Map<String, String> map = new HashMap<String, String>();

try {
database = hximusersqlhelper.getWritableDatabase();

cursor = database.query(false, TABLE_NAME, null, selection,
selectionArgs, null, null, null, null);
int cols_len = cursor.getColumnCount();
while (cursor.moveToNext()) {
for (int i = 0; i < cols_len; i++) {
String cols_name = cursor.getColumnName(i);
String cols_values = cursor.getString(cursor
.getColumnIndex(cols_name));
if (cols_values == null) {
cols_values = "";
}
map.put(cols_name, cols_values);
}
}

} catch (Exception e) {
// TODO: handle exception
} finally {
if (database != null) {
database.close();
}
}

return map.get(COLUMN_NAME_FACE);

}

3.关于注册,由于环信的提倡的是用REST API 注册,不是在app里面,所以注册接口逻辑是,当用户提交账号 和密码我就在自己的数据库中添加一条记录并且返回uid,然后用uid和经过加密后的密码 去向环信提交注册。
 //$result为0注册失败
//注册成功后再取hx注册 ,成功则返回result为true
//否则返回false同时删除再app服务器上的注册
if ($result) {

$registcondition['user_id']=$result;
$User=$this->model->table('user');
$registinfo=$User->where($registcondition)->find();

$hxoptions['username']=$registinfo['user_id'];
$hxoptions['password']=$registinfo['user_userpass'];

$mooptions['client_id']=$this->config['CLIENT_ID'];
$mooptions['client_secret']=$this->config['CLIENT_SECRET'];
$mooptions['org_name']=$this->config['ORG_NAME'];
$mooptions['app_name']=$this->config['APP_NAME'];

require_once('Easemob.class.php');
$Easemob = new Easemob($mooptions);
$hxregisterresult= $Easemob->accreditRegister($hxoptions);

if ($hxregisterresult['status']==200) {
$result=true;
}else{
$deleteuser['user_id']=$result;
$deleteresult=$User->where($deleteuser)->delete();
$result=false;
}
}

注意,如果在环信上如果注册失败,则要在本地删除这条记录,以免用处再次cha尝试注册的时候 ,提示已经注册,但其实环信没有注册成功所以无法登陆。修改密码也是这样的 。
 
建议:在sdk里面,好像没有将该会话置顶的方法。而是统一按照最后消息排序
 
最后感谢下环信,不管从消息下发,文档,sdk,以及客服各个方面来说都做的不错。最后提交一张我自己集成会话的页面截图。
  收起阅读 »

集成环信时遇到的问题


"_ASN1_INTEGER_get",
referenced from:
_get_cert_info in
libEaseMobClientSDKLite.a(ssl_sock_ossl.o)



今天集成环信,可能是因为之前导入过多第三方静态库的原因,导致出现以上75个错去,貌似说编译的时候不能找到.a文件,在真机上可以跑,但在模拟器上就出现此错误,现将我出现错误的原因及解决方法晒出,希望可以帮助将来跟我一样遇到困难的人.


原因如下:在Build Settings下Linking 下的other Linker Flags中添加了-ObjC、-all_load或-force_load从而导致出现上述问题



在Build Settings下Linking 下的other Linker Flags 只保留-ObjC即可
 
继续阅读 »

"_ASN1_INTEGER_get",
referenced from:
_get_cert_info in
libEaseMobClientSDKLite.a(ssl_sock_ossl.o)



今天集成环信,可能是因为之前导入过多第三方静态库的原因,导致出现以上75个错去,貌似说编译的时候不能找到.a文件,在真机上可以跑,但在模拟器上就出现此错误,现将我出现错误的原因及解决方法晒出,希望可以帮助将来跟我一样遇到困难的人.


原因如下:在Build Settings下Linking 下的other Linker Flags中添加了-ObjC、-all_load或-force_load从而导致出现上述问题



在Build Settings下Linking 下的other Linker Flags 只保留-ObjC即可
  收起阅读 »

关于集成环信即时通讯的文章

环信的Web IM即时通讯聊天室的聊天记录不能保存,有的用户想要翻看以前的聊天记录看,找不到当时的聊天记录,调用环信Web IM的相关api也只能调取一部分,不能充分的满足开发的需求。
环信的Web IM即时通讯聊天室的聊天记录不能保存,有的用户想要翻看以前的聊天记录看,找不到当时的聊天记录,调用环信Web IM的相关api也只能调取一部分,不能充分的满足开发的需求。

iOS 环信 集成 详细步骤图文

环信的教程:

没有初始化SDK  

去AppDelegate里面初始化

 

密码

 

User not exist         ??????????

每一个应用都有自己的注册用户  去你的后台管理   去看你的注册的用户数   

为什么demo的可以跑起来????????

是在它的应用下注册的

 

怎么去注册用户  -注册用户

用户名字可以相同   不同的应用   

 

 

那个打印的loginInfo 是这个字典的也就是用户的登录信息

 

你会发现打印的loginInfo上面还有一坨恶心的东西,那个是环信SDK自己打印的日志信息

 

SEND   和      RECV    使用的是XMPP协议    所以 数据的格式是XML   一般的HTTP协议的话他就是JSON格式的

这个是app把客户端登录的信息发给环信服务器后打印出来的日志      是不是很烦

 

如何去在哪儿隐藏它的控制台的日志信息 ?????????

去初始化的时候把它隐藏  有一个otherConfig的东西   右键-jump to Define

进去瞅瞅--

复制它的key 给他设置为NO

这个时候它的控制台的日志信息就被屏蔽了

 

 

跟环信交互的所有类都有这个

[EaseMob sharedInstance].chatManager

 

 

注册的时候代码:


如果你把这onQueue改为nil的话他默认也是在主线程的

 

然后你在去环信的开发中心刷新IM用户 你会发现他多了一个

发送给的数据给服务器的时候还是XML格式,里面的SDK帮你封装了,不用你自己去接触

 

 

---自动登录------------------------------------

 

看到它的主界面只有三个tabbar

 进去 mainstoryboard里面 删除原始的viewcontroller  拖入一个 tabbarController     去掉原始的tabbar 的两个子控制器   记得给它的isinitial 那个选项钩上   然后拖入三个navigationcontroller(这个根据你的界面而定)

 

选中给每个的Item  的title属性可以更改

然后在登录成功中写上加载storyboard的方法

你会发现你已经跳转进去
如何实现自动登录?????????????????

  实现原理:把你的登录信息保存在沙盒中     程序启动时候发送登录请求

  只要你在第一次登录成功后发送环信自带登录的网络请求去实现、

环信自己帮你实现上面的东西

 

具体实现

在登录成功的下面写上

[[EaseMob sharedInstance].chatManager  setIsAutoLoginEnabled:YES]

然后去在AppDelegte里面把他的沙盒路径拿到
然后再控制台你可以看到这些信息,其中的账号密码信息你会发现他被加密了,有没有?
如何监听是否是已经处于登录状态了这个地方有个代理  环信的代理方法

在AppDelegate方法里面进去 在启动方法里面写
你会发现它的那个啥没有完成界面的跳转    但是控制台却是带那个登陆成功了
这个时候我们还缺一步骤  之前我们在自动登录时候我们调用的是set方法

这个时候我们要实现它的 get方法     写在监听登录状态的下面

  //如果登录过直接来到主界面
    if([[EaseMob sharedInstance].chatManager isAutoLoginEnabled]){

        self.window.rootViewController = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;

    }

    
=------------自动连接--------------------------

 

网络通不通的时候类似微信那种网络不通的实现

去那个main.storyboard里面把那会话的导航控制器跳转的那个类继承改为你自己创建的那个UItableViewController

 

1.在会话里面监听的网络的状态  环信的有很多个代理

去那个.m文件里面去实现
点击那个EMChatManagerDelegate 里面去实现 EMChatManagerUtilDelegate里面的这个方法就OK了

- (void)didConnectionStateChanged:(EMConnectionState)connectionState;
在真机上面测试的时候 网络连接成功不代表客户端和服务器端连接成功

 

 

还有自动连接的状态的监听 也是加上他的代理方法就行了


--------添加好友请求-----------------------------

1.是用环信的思想

 所有的网络请求   [EaseMob sharedInstance].chatManager 由这个管理器发起的

 

2.所有结果(自动登录 自动连接)通过代理来回调完成

[EaseMob sharedInstance].chatManager的addDelegate来完成

 

3.EMChatManagerBuddyDelegate 这个代理实现了对用户的基本操作

1.添加好友      2.从本地获取好友      3.从服务器列表获取最新的好友     4.接受好友添加请求

5.删除好友       6.被好友从名单上面删除  

 

 

在navigation  的第二个控制器上面加上一个UIbarbarItem   选择自定义   然后+    

再去创建一个UIviewController     然后再去实现用个+号去拖一个线  

 

 可以在上面加上navigationItem 上改为添加好友

再去新建一个控制器AdressBooking 通讯录  这个类是继承于UIviewController
是用环信最简单的方法 ,把官方的Demo直接拿过来用   直接跟改它的Appdelegate里面的APPKey

这样你就收到了申请    注意   这是最简单的方式

 

 

还有一点 你要在每个控制器里面写上你环信的代理方法

这样就能保证你下面写的环信 的每一个方法会被自动调用了
代理方法:

代理的销毁

 

 

好友请求消息反馈写在什么地方   因为你进去那个会话的控制器里面了的话就会被销毁了。我们可以把它的好友请求写在会话控制器   这样他每个控制器都可以收到了  也没有必要写在AppDelegate里面 可以去尝试一下

 

 

 

 

 

 

 

 

 

 

---------现实好友界面列表------------------

1.新建一个tableViewcontroller  修改那个tableView的继承

 

2.给他的cell添加一个Identifier     
下面打印的就是他的好友列表

 

 

#pragma mark - Tableview datasource

 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.buddyList.count;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *ID = @"BuddyCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    //获取好友列表名称  EMBuddy是环信封装的好友模型

    EMBuddy *buddy = self.buddyList[indexPath.row];

    //显示头像 和名字

    cell.imageView.image = [UIImage imageNamed:@"chatListCellHead"];

    cell.textLabel.text = buddy.username;

    

    return cell;

}

 

注意一个bug在网速很慢的时候话或者用户的手速很快的情况下(遇到单身30年的手速)用户的时候      你会发现好友列表但是没有值的  因为它的好友列表是在你用户登录策划国内恭候才会有值 

 

buddyList是从本地获取的数据  本地有个数据库你可以去里面看看  

// buddyList 

 

如果删除了应用或者饿用户第一次登陆的时候 buddyList是没有数据记录的

就要从服务区获取好友列表纪录

 

 

在网络登陆之前我们去从服务器获取那个 好友列表并把它写到本地的数据库里面去,注意一下这个方法写在哪个地方 切记切记
----------------好友请求同意后的列表刷新----------------------------

 

当接收到后有的同意后要刷新好友的列表数据   去通讯录控制器监听
产生了一个问题?

我发送了请求   对方接受了   没有刷新好友列表

环信发送的话一定调用了

#pragma mark-好友列表的请求被更新,然而并没什么卵用

-(void)didUpdateBuddyList:(NSArray *)buddyList changedBuddies:(NSArray *)changedBuddies isAdd:(BOOL)isAdd{

//    NSLog(@"好友列表被更新%@", buddyList);

    NSLog(@"%@",buddyList);

    self.buddyList = buddyList;

    [self.tableView reloadData];

    

}

加上这句话就可以解决这个问题

 

 

 

 

============删除好友==========================

 

 

获取移除好友的名字

还有一种删除了是互相删除还是只是将一方的删除

 

#pragma mark--删除好友的代理方法

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath {

    if(editingStyle == UITableViewCellEditingStyleDelete) {

        //获取要移除的好友的名字

        EMBuddy *buddy =self.buddyList[indexPath.row];

        NSString *deleteusername  = buddy.username;

        

        //删除好友

        [[EaseMob sharedInstance].chatManager removeBuddy:deleteusername removeFromRemote:YES error:nil];

    }

}

 

 

 

 

 

———--------被好友删除的监听-----------------------------

1.在会话里面:

//被好友删除

#pragma mark-监听被好友删除

-(void)didRemovedByBuddy:(NSString *)username {

    NSString *message = [username stringByAppendingString:@"把你删除"];

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"好友删除提醒" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

    [alert show];

}

 

在同叙录里面:

//监听被删除去会话里面

#pragma mark-被好友删除了刷新一遍列表

-(void)didRemovedByBuddy:(NSString *)username {

    [self loadDataFromServer];

}

 

--------------退出登录--------------------------

 

选中table View 的然后给他选static cell

   2.然后连线去实现它的方法

 

-重点-------------聊天界面的实现----------------------------

 

1.拖入一个UIviewController 在上面在取拖入一个navagationBar 去设置他的标题

 

2.把cell的脱线  show

 

3.拖入一个View   拖到最下面    你会发现被tabbar 给盖住了   怎么去隐藏他呢?

   选中他   有个 Bottom Bar  改为None   

 

4.给这个View设置约束的时候注意  不要给她设置底部距Bottom  选择View

layout后  选择 Hidden Bottom Bar

 

5.往上面添加button    button也要设置约束  要他举例底部的位子不变    

否者的话  他会随着聊天的界面文字的的增加   而那个上升

 

还要加上一个textfield

 

通过代码监听键盘    如果底部
千万不要把键盘关闭了   不然神仙也救不了你

 

具体代码:

 

-(void)viewDidLoad {

    [super viewDidLoad];

    //1.监听键盘的弹出,把inputToolbar往上移

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

    

    

    

}

 

#pragma mark-键盘显示的时候会触发方法

-(void)kbWillShow:(NSNotification *)notification {

 //获取键盘的高度

    //1.获取键盘结束的位子

    CGRect kbEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

    CGFloat kbHeight = kbEndFrame.size.height;

    

    //更改inputToolBar的底部约束

    self.inputToolBarBottonConstraint.constant = kbHeight;

    //添加动画

    [UIView animateWithDuration:0.25 animations:^{

        [self.view layoutIfNeeded];

    }];

}

 

//移除通知

 

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

///////////////////

再加上一个tableView在它的上面    如何实现在拖动tableview 的时候让键盘隐藏

 

或者去监听tableView滚动的方法  

 

tableView 有一个属性 Keyboard  Dismiss on drag

在键盘推出的时候 让inputToolBarView  恢复原位

也要监听他

 

 

 

 

-----------cell有三种类型的 左边  中间   右边 -------------------------

1.往那个tableView里面去添加cell的时候我们可以 在里面加上图片

 

思路:在你设置好了头像之后再去设置文本的时候怎么设置

UILabel 设置背景图片的时候 我们可以先去给UILabel设置约束

再去设置那个背景图片,让他去拉伸

设置约束的时候注意头像要写死  但是lable只需要设置他的左边和  上面就行

 

如何加上测试数据:

1.自定一一个cell   在给他对用的类    和 对应的cell  绑定一个改类名

在。h文件里面给label加上一个属性 , 在给他的cell绑定一cell
最后别忘了在给tableview 右键往那个UIviewController上面加上数据源和代理

也就是自定义cell

 

------如何去让他显示的换行

1.吧label的Lines设置为0;

2.设置她的最大宽度:选择  Preferred width 这个选项242;

 

 

----最后给他设置那个背景图片

吧那个UIimage添加到那个Label上面 

如何给那个这个ImageView 和Label  设置左上角对其?????????????

选中他们两个,然后把选择设置约束右下角的正向第2个  然后把4个Edge选择对其

 

最后别忘了去吧label  设置为clear

 

怎么去把ImageView的背景图片拉伸???????

选择背景图片 第4个属性倒立的脚   有一个strecting属性  设置为0.5   0.5  0  0

那个时候你会发现它的那个啥的没有那个左边图片的角的属性,什么原因呢?

这是因为你的这个时候的Y值拉升的不够可以把他的Y方向上面改成 0.7

 

这个时候还缺最后一步,要把它的那个背景ImagView改动一下,让它在上下左右 都往外面 

拉伸一下??????//

可以选中它的那个约束,更改它的那个Constant    左边和上面的都是 加10     下边和右边是减10

 最后别忘了跟新约束

 

-----------发送方的cell排布----------------------

先拖入一tableViewCell 然后改他的名字    在去拖入一个Imageview  在去实现它的那个

5  5   35 35 

2.拖入一个Label   上面15 右边20   宽和高就不要添加了

 

3.如何让两个自定义的cell指向同一个的cell  新思想 :两个View公用一个cell

  连线的时候又一个选择   选择senderCell   再给SenderCell一个identifier标示符号

在渲染cell的方法中加入一个加载哪一个cell的判断

 

4.最后设置它的Lines = 0  和 那个Preferred Width的宽度  让它实现自动换行

 

5.添加一个ImageView然后再去设置它的背景图片和  那个边距的对其

 

6.更改Image的Stretching

 

7.最后去把ImageView 的各个边距都改一下 上 10   左 10    下 -10  右边  -15 最后跟新

 

8  重点----如何去根据label里面的文字的高度去自动计算那个文字的高度?????

1.实现它的给他添加了一个测试的数据源方法

9--重点----还有一个问题  怎么去更改的它的自动计算那个行高呢??????

cell的高度取决于label文字的高度和它的字体的大小决定的、

思想: 去获取那个cell里面的label的高度再去加上一个固定的高度就是cell的高度了

怎么去获取那个label的高度呢???

上面的额头像距上为5 加上那个上面label距离上面的10的高度 再加上label自己      的高度self.label.hight +下面的那个10,再去加上那个固定的高度就是cell的高度了

 

 

10.--重点----我们专门搞一个计算高度的属性(他是一个返回cell的方法,然后去返回cell高度的方法里面去给他完成一下赋值的操作,最后去实现)

  //还少了一步 ,一定要加上去设置那个label的数据

    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

    return [self.chatCellTool cellHeight];

 

 

/** 计算高度的cell的属性*/

 @property (nonatomic,strong)UXZYChatCell *chatCellTool;

 

   //给计算cell高度的对象完成一个赋值

    //他返回的是一个cell 这个cell只是在那个返回高度的方法里面去用到了,其他的地方没有用到

记得最好把它的方法static NSString *Indentifier = @"ReceiveCell";写在那个cell的.h文件中

tableview记得再拖一次线  为什么任何一个的Identifier:都可以呢?????

因为你在返回高度的方法里面都是一样的执行的,不获去细分你是哪一个cell的方法 so。。。

    self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:SenderCell];

 

 

--------------发送聊天消息---------------------

1.首先要做的是把那个 textView的发送框改成send属性 第四个选项里面的有一个

  Return Key 选项 改成那个Send选项

 

2.怎么去发送按钮的事件呢?????

1.把那个textView 的代理的线连上   2.然后去那个tableView里面的那个去遵守textView代理

 

在textView的方法里面去监听他最后的字符有没有换行,如果有换行的字符的话我就代表说他是发送sender的按钮]

 

3.怎么去发送文字呢???????

#pragma mark-UITextView的代理

-(void)textViewDidChange:(UITextView *)textView {

    if([textView.text hasSuffix:@"\n"] ) {

        NSLog(@"这是一个发送事件");

        //发送文字

        [self sendMessage:textView.text];

        

        //清空文字

        textView.text = nil;

    

    }

}

 

-(void)sendMessage:(NSString *)text {

    //创建一个消息对象实例

    EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:nil bodies:nil];

    //发送消息

    [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

        NSLog(@"消息准备发送");

    } onQueue:nil completion:^(EMMessage *message, EMError *error) {

        NSLog(@"消息完成发送");

    } onQueue:nil];

    

}

还缺少一个参数  就是把消息发送给谁? 我们就缺少一个参数传递

initWithReceiver:要去拿到那个参数好友列表的参数 EMBuddy 

#warning 每一种消息类型对象不同的消息体

    //EMTextMessageBody

    //EMVoiceMessageBody

    //EMVideoMessageBody

   // EMLocationMessageBody

   // EMImageMessageBody

    

    //创建一个聊天的文本对象

    EMChatText *chatText = [[EMChatText alloc]initWithText:text];

    //创建一个文本消息体

    EMTextMessageBody *textBody = [[EMTextMessageBody alloc]initWithChatObject:chatText];

    

    //创建一个消息对象实例   bodies是一个数组

    EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

    //发送消息

    

    [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

        NSLog(@"消息准备发送");

    } onQueue:nil completion:^(EMMessage *message, EMError *error) {

        NSLog(@"消息完成发送");

    } onQueue:nil];

 

注意点  : 加上一个return;去测试

把选中的好友列表正向传递进去

最后别忘了把那个return打开;

    

 

--------------显示好友的名字---------------------

1.在那个聊天的控制器的viewdidload里面写上

self.titlte = self.buddy.username

 

——————-------加载本地的聊天数据--------------------

有封装好的东西,先去内存的会话列表中去获取会话  如果没有找到就去数据库中去获取会话

没有找到就会出发现的会话

 

#pragma mark-加载本地的聊天数据 

-(void)loadLocalChatrecords {

    //获取本地聊天记录 会话对象

   EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.buddy.username conversationType: eConversationTypeChat];

    //加载当前来哦天用户所有的聊天记录

    NSArray *messages = [conversation loadAllMessages];

    

    for(id obj in messages) {

        NSLog(@"%@",[obj class]);

    }

    

    [self.dataSources addObject:messages];

    

}

 

  [self.dataSources addObject:messages];加上了就报错了,她的原因是什么呢?

  tableView:heightForRowAtIndexPath 错了

 

跳进设置高度的方法里面去 去吧里面改动一下

    //改进后的cell高度的获取

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

//    EMMessage *msg = self.dataSources[indexPath.row];

//    id body = msg.messageBodies[0];

//    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

//        EMTextMessageBody *textBody = body;

//        cell.messageLabel.text = textBody;

//    }

 

最后是用一个set方法去代替他们

 

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

    EMMessage *msg = self.dataSources[indexPath.row];

    //改进后的cell高度的获取

//    id body = msg.messageBodies[0];

//    

//    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

//        EMTextMessageBody *textBody = body;

//        cell.messageLabel.text = textBody;

//    }

    self.chatCellTool.message = msg;

    return [self.chatCellTool cellHeight];

    

    //还少了一步 ,一定要加上去设置那个label的数据

//    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

//    return [self.chatCellTool cellHeight];

}

最后别忘了去那个tableviewcell的模型里面去改,

 

————为了计算高度我们建立了一个模型——----------

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

     //改进后的cell高度的获取

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

    EMMessage *msg = self.dataSources[indexPath.row];

    

    self.chatCellTool.message = msg;

    

    return [self.chatCellTool cellHeight];

}

重写了模型的set方法 ,然后去调用了他的set方法

 

最后别忘了在显示的时候去调用他渲染那个方法

我的这个msg是一个消息模型

msg.messageBodies[0]

这样才能拿到消息体

msg.messageBodies[0].text才正确

 

-------------

[Pasted Graphic.tiff]

----------这样还不对-------------------------

 

你会看到你发出去的消息会在左边能看到

如何让它只能在右边显示呢??????????/

EMmessage有两个属性 from   to

from是发送方也就是自己    from是好友的话自己就是接受方

所以我们得在现实渲染的方法里面去先去获取消息模型

然后再去做一个from的判断

 

    UXZYChatCell *cell = nil;

    //先去获取消息模型然后去在去判断是发送方还是接收方

    EMMessage *msg = self.dataSources[indexPath.row];

    if([msg.from isEqualToString:self.buddy.username]) {//自己接收方

       cell = [tableView dequeueReusableCellWithIdentifier:Indentifier];

    }else {

       cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];

    }

 

--------怎么让你的消息立马显示-----------------------

去这个方法里面 

-(void)sendMessage:(NSString *)text { }

 

msgObj是你自己创建一个消息对象实例   bodies是一个数组

 EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

    //把消息添加到数据源 再刷新表格

    [self.dataSources addObject:msgObj];

    [self.tableView reloadData];

 

------怎么让你的消息自己滚动到最上面的一行----

   

    //4.把消息显示在顶部

    [self scrollToBottom];

}

 

-(void)scrollToBottom {

    //获取最后一行

    if(self.dataSources.count == 0){

        return;

    }

    NSIndexPath *lastIndex = [NSIndexPath indexPathForRow:self.dataSources.count-1 inSection:0];

    

    

    [self.tableView scrollToRowAtIndexPath:lastIndex atScrollPosition:UITableViewScrollPositionBottom animated:YES];

}

 

—————仔细的你到这一步了发没发现你那个你发出去的消息子啊框里面都会多出一行---

原因:是你在点击发送的时候他换了一下行,换行字符只展占用一个字节

如何去清除那个换行的字符,在发消息的放里面去实现

        text = [text substringToIndex:text.length-1];

 

 

-----------怎么去监听消息的回复--------------------

1.设置代理方法  并遵循它的 代理方法

2.有一个那个mesage的方法去实现一下

 

 

 

 

------对输入框的完善,即在你输入的时候那个输入框的高速会自动增加-------------------------

1.得定义输入框的一个最小的高度和最大的高度

2.textView是继承于UIscrollView   scrollView有一个属性 contensize 属性

    这个是计算那个做一个判断 不同情况下面的高度

 

3.我们再去拿到那个的InputView 的高度的约束  再去连线使它成为一个属性  然后像之前一样去约束它,找到他,然后给他连线 使它成为一个属性

 

    //获取contentsize的高度

    CGFloat contentHeight = textView.contentSize.height;

    if (contentHeight <minHeight) {

        textViewH = minHeight;

    }else if (contentHeight >maxHeight) {

        textViewH = maxHeight;

    }else {

        textViewH = contentHeight;

    }

    

    self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

 

4.还是有一个问题,就是在你输入完了一之后发送了   之后textView还是有一个换行的空格

所以还得有一个在发送完了后的判断语句

if([textView.text hasSuffix:@"\n"] ) {

        NSLog(@"这是一个发送事件");

        //发送文字

        [self sendMessage:textView.text];

        

        //清空文字

        textView.text = nil;

        

//        发送时textView的高速为最小的高度

        textViewH = minHeight;

    

    }

    self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

 

5.设置textView的背景图片  在SB中去设置 拖入一个IMageView 然后把它拿到那个textView的上面去   然后改透明  设置背景图片    把图片拉伸  streching  别忘了给背景图片加约束 不然的话他会随着那个的高度的增加他不会随着拉伸   最后去加个动画

 

6.——————---发送完了后发现光标不见了 发大模拟器看在左上角???

原因???scrollView有一个contentOffset.y的值会随着你的那个的光标的contensize的而向上拖动而拖送

NSStringFromCGSize(textView.contentSet)可以打印出来看看

contentOffset一开始为(0,0)之后它的y值为正数了,为什么呢,因为他要显示的下面的文字内容的话它的那个轴必须下移动 所以为正 

如何解决  哪次发送完了 让它的contentset恢复到原位

 

 

环信遇到的bug1:真机上面不能跑  模拟器可以

[Pasted Graphic_1.tiff]

 

把那个bitcode 设置为NO  bitcode是被编译程序的一种中间形式的代码。包含bitcode配置的程序将会在App store上被编译和链接

默认是yes   

 

 

storyboard作为控制器的复习

 

1.拖入一导航控制器 ,更改尺寸    去掉后一个

2.拖入一个viewControler  然后去把它的那个root viewcontroller  设置一下

 

3.创建一个控制器UIviewcontroller     第三个选项 class里面更改继承关系   

 

 

4.拖线 连线        1.去改掉main        2。去那个第4个 is initial  View Controller 的钩上

 

 

登录提供了三种方法

 

 

1.同步     2.block的异步      3.代理的回调

 

注释的方法提示在图表

方式一:/// 点在图标

方式二: 

 /*!

 *   @brief 点在图标

 */
继续阅读 »
环信的教程:

没有初始化SDK  

去AppDelegate里面初始化

 

密码

 

User not exist         ??????????

每一个应用都有自己的注册用户  去你的后台管理   去看你的注册的用户数   

为什么demo的可以跑起来????????

是在它的应用下注册的

 

怎么去注册用户  -注册用户

用户名字可以相同   不同的应用   

 

 

那个打印的loginInfo 是这个字典的也就是用户的登录信息

 

你会发现打印的loginInfo上面还有一坨恶心的东西,那个是环信SDK自己打印的日志信息

 

SEND   和      RECV    使用的是XMPP协议    所以 数据的格式是XML   一般的HTTP协议的话他就是JSON格式的

这个是app把客户端登录的信息发给环信服务器后打印出来的日志      是不是很烦

 

如何去在哪儿隐藏它的控制台的日志信息 ?????????

去初始化的时候把它隐藏  有一个otherConfig的东西   右键-jump to Define

进去瞅瞅--

复制它的key 给他设置为NO

这个时候它的控制台的日志信息就被屏蔽了

 

 

跟环信交互的所有类都有这个

[EaseMob sharedInstance].chatManager

 

 

注册的时候代码:


如果你把这onQueue改为nil的话他默认也是在主线程的

 

然后你在去环信的开发中心刷新IM用户 你会发现他多了一个

发送给的数据给服务器的时候还是XML格式,里面的SDK帮你封装了,不用你自己去接触

 

 

---自动登录------------------------------------

 

看到它的主界面只有三个tabbar

 进去 mainstoryboard里面 删除原始的viewcontroller  拖入一个 tabbarController     去掉原始的tabbar 的两个子控制器   记得给它的isinitial 那个选项钩上   然后拖入三个navigationcontroller(这个根据你的界面而定)

 

选中给每个的Item  的title属性可以更改

然后在登录成功中写上加载storyboard的方法

你会发现你已经跳转进去
如何实现自动登录?????????????????

  实现原理:把你的登录信息保存在沙盒中     程序启动时候发送登录请求

  只要你在第一次登录成功后发送环信自带登录的网络请求去实现、

环信自己帮你实现上面的东西

 

具体实现

在登录成功的下面写上

[[EaseMob sharedInstance].chatManager  setIsAutoLoginEnabled:YES]

然后去在AppDelegte里面把他的沙盒路径拿到
然后再控制台你可以看到这些信息,其中的账号密码信息你会发现他被加密了,有没有?
如何监听是否是已经处于登录状态了这个地方有个代理  环信的代理方法

在AppDelegate方法里面进去 在启动方法里面写
你会发现它的那个啥没有完成界面的跳转    但是控制台却是带那个登陆成功了
这个时候我们还缺一步骤  之前我们在自动登录时候我们调用的是set方法

这个时候我们要实现它的 get方法     写在监听登录状态的下面

  //如果登录过直接来到主界面
    if([[EaseMob sharedInstance].chatManager isAutoLoginEnabled]){

        self.window.rootViewController = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;

    }

    
=------------自动连接--------------------------

 

网络通不通的时候类似微信那种网络不通的实现

去那个main.storyboard里面把那会话的导航控制器跳转的那个类继承改为你自己创建的那个UItableViewController

 

1.在会话里面监听的网络的状态  环信的有很多个代理

去那个.m文件里面去实现
点击那个EMChatManagerDelegate 里面去实现 EMChatManagerUtilDelegate里面的这个方法就OK了

- (void)didConnectionStateChanged:(EMConnectionState)connectionState;
在真机上面测试的时候 网络连接成功不代表客户端和服务器端连接成功

 

 

还有自动连接的状态的监听 也是加上他的代理方法就行了


--------添加好友请求-----------------------------

1.是用环信的思想

 所有的网络请求   [EaseMob sharedInstance].chatManager 由这个管理器发起的

 

2.所有结果(自动登录 自动连接)通过代理来回调完成

[EaseMob sharedInstance].chatManager的addDelegate来完成

 

3.EMChatManagerBuddyDelegate 这个代理实现了对用户的基本操作

1.添加好友      2.从本地获取好友      3.从服务器列表获取最新的好友     4.接受好友添加请求

5.删除好友       6.被好友从名单上面删除  

 

 

在navigation  的第二个控制器上面加上一个UIbarbarItem   选择自定义   然后+    

再去创建一个UIviewController     然后再去实现用个+号去拖一个线  

 

 可以在上面加上navigationItem 上改为添加好友

再去新建一个控制器AdressBooking 通讯录  这个类是继承于UIviewController
是用环信最简单的方法 ,把官方的Demo直接拿过来用   直接跟改它的Appdelegate里面的APPKey

这样你就收到了申请    注意   这是最简单的方式

 

 

还有一点 你要在每个控制器里面写上你环信的代理方法

这样就能保证你下面写的环信 的每一个方法会被自动调用了
代理方法:

代理的销毁

 

 

好友请求消息反馈写在什么地方   因为你进去那个会话的控制器里面了的话就会被销毁了。我们可以把它的好友请求写在会话控制器   这样他每个控制器都可以收到了  也没有必要写在AppDelegate里面 可以去尝试一下

 

 

 

 

 

 

 

 

 

 

---------现实好友界面列表------------------

1.新建一个tableViewcontroller  修改那个tableView的继承

 

2.给他的cell添加一个Identifier     
下面打印的就是他的好友列表

 

 

#pragma mark - Tableview datasource

 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.buddyList.count;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *ID = @"BuddyCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    //获取好友列表名称  EMBuddy是环信封装的好友模型

    EMBuddy *buddy = self.buddyList[indexPath.row];

    //显示头像 和名字

    cell.imageView.image = [UIImage imageNamed:@"chatListCellHead"];

    cell.textLabel.text = buddy.username;

    

    return cell;

}

 

注意一个bug在网速很慢的时候话或者用户的手速很快的情况下(遇到单身30年的手速)用户的时候      你会发现好友列表但是没有值的  因为它的好友列表是在你用户登录策划国内恭候才会有值 

 

buddyList是从本地获取的数据  本地有个数据库你可以去里面看看  

// buddyList 

 

如果删除了应用或者饿用户第一次登陆的时候 buddyList是没有数据记录的

就要从服务区获取好友列表纪录

 

 

在网络登陆之前我们去从服务器获取那个 好友列表并把它写到本地的数据库里面去,注意一下这个方法写在哪个地方 切记切记
----------------好友请求同意后的列表刷新----------------------------

 

当接收到后有的同意后要刷新好友的列表数据   去通讯录控制器监听
产生了一个问题?

我发送了请求   对方接受了   没有刷新好友列表

环信发送的话一定调用了

#pragma mark-好友列表的请求被更新,然而并没什么卵用

-(void)didUpdateBuddyList:(NSArray *)buddyList changedBuddies:(NSArray *)changedBuddies isAdd:(BOOL)isAdd{

//    NSLog(@"好友列表被更新%@", buddyList);

    NSLog(@"%@",buddyList);

    self.buddyList = buddyList;

    [self.tableView reloadData];

    

}

加上这句话就可以解决这个问题

 

 

 

 

============删除好友==========================

 

 

获取移除好友的名字

还有一种删除了是互相删除还是只是将一方的删除

 

#pragma mark--删除好友的代理方法

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath {

    if(editingStyle == UITableViewCellEditingStyleDelete) {

        //获取要移除的好友的名字

        EMBuddy *buddy =self.buddyList[indexPath.row];

        NSString *deleteusername  = buddy.username;

        

        //删除好友

        [[EaseMob sharedInstance].chatManager removeBuddy:deleteusername removeFromRemote:YES error:nil];

    }

}

 

 

 

 

 

———--------被好友删除的监听-----------------------------

1.在会话里面:

//被好友删除

#pragma mark-监听被好友删除

-(void)didRemovedByBuddy:(NSString *)username {

    NSString *message = [username stringByAppendingString:@"把你删除"];

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"好友删除提醒" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

    [alert show];

}

 

在同叙录里面:

//监听被删除去会话里面

#pragma mark-被好友删除了刷新一遍列表

-(void)didRemovedByBuddy:(NSString *)username {

    [self loadDataFromServer];

}

 

--------------退出登录--------------------------

 

选中table View 的然后给他选static cell

   2.然后连线去实现它的方法

 

-重点-------------聊天界面的实现----------------------------

 

1.拖入一个UIviewController 在上面在取拖入一个navagationBar 去设置他的标题

 

2.把cell的脱线  show

 

3.拖入一个View   拖到最下面    你会发现被tabbar 给盖住了   怎么去隐藏他呢?

   选中他   有个 Bottom Bar  改为None   

 

4.给这个View设置约束的时候注意  不要给她设置底部距Bottom  选择View

layout后  选择 Hidden Bottom Bar

 

5.往上面添加button    button也要设置约束  要他举例底部的位子不变    

否者的话  他会随着聊天的界面文字的的增加   而那个上升

 

还要加上一个textfield

 

通过代码监听键盘    如果底部
千万不要把键盘关闭了   不然神仙也救不了你

 

具体代码:

 

-(void)viewDidLoad {

    [super viewDidLoad];

    //1.监听键盘的弹出,把inputToolbar往上移

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

    

    

    

}

 

#pragma mark-键盘显示的时候会触发方法

-(void)kbWillShow:(NSNotification *)notification {

 //获取键盘的高度

    //1.获取键盘结束的位子

    CGRect kbEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

    CGFloat kbHeight = kbEndFrame.size.height;

    

    //更改inputToolBar的底部约束

    self.inputToolBarBottonConstraint.constant = kbHeight;

    //添加动画

    [UIView animateWithDuration:0.25 animations:^{

        [self.view layoutIfNeeded];

    }];

}

 

//移除通知

 

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

///////////////////

再加上一个tableView在它的上面    如何实现在拖动tableview 的时候让键盘隐藏

 

或者去监听tableView滚动的方法  

 

tableView 有一个属性 Keyboard  Dismiss on drag

在键盘推出的时候 让inputToolBarView  恢复原位

也要监听他

 

 

 

 

-----------cell有三种类型的 左边  中间   右边 -------------------------

1.往那个tableView里面去添加cell的时候我们可以 在里面加上图片

 

思路:在你设置好了头像之后再去设置文本的时候怎么设置

UILabel 设置背景图片的时候 我们可以先去给UILabel设置约束

再去设置那个背景图片,让他去拉伸

设置约束的时候注意头像要写死  但是lable只需要设置他的左边和  上面就行

 

如何加上测试数据:

1.自定一一个cell   在给他对用的类    和 对应的cell  绑定一个改类名

在。h文件里面给label加上一个属性 , 在给他的cell绑定一cell
最后别忘了在给tableview 右键往那个UIviewController上面加上数据源和代理

也就是自定义cell

 

------如何去让他显示的换行

1.吧label的Lines设置为0;

2.设置她的最大宽度:选择  Preferred width 这个选项242;

 

 

----最后给他设置那个背景图片

吧那个UIimage添加到那个Label上面 

如何给那个这个ImageView 和Label  设置左上角对其?????????????

选中他们两个,然后把选择设置约束右下角的正向第2个  然后把4个Edge选择对其

 

最后别忘了去吧label  设置为clear

 

怎么去把ImageView的背景图片拉伸???????

选择背景图片 第4个属性倒立的脚   有一个strecting属性  设置为0.5   0.5  0  0

那个时候你会发现它的那个啥的没有那个左边图片的角的属性,什么原因呢?

这是因为你的这个时候的Y值拉升的不够可以把他的Y方向上面改成 0.7

 

这个时候还缺最后一步,要把它的那个背景ImagView改动一下,让它在上下左右 都往外面 

拉伸一下??????//

可以选中它的那个约束,更改它的那个Constant    左边和上面的都是 加10     下边和右边是减10

 最后别忘了跟新约束

 

-----------发送方的cell排布----------------------

先拖入一tableViewCell 然后改他的名字    在去拖入一个Imageview  在去实现它的那个

5  5   35 35 

2.拖入一个Label   上面15 右边20   宽和高就不要添加了

 

3.如何让两个自定义的cell指向同一个的cell  新思想 :两个View公用一个cell

  连线的时候又一个选择   选择senderCell   再给SenderCell一个identifier标示符号

在渲染cell的方法中加入一个加载哪一个cell的判断

 

4.最后设置它的Lines = 0  和 那个Preferred Width的宽度  让它实现自动换行

 

5.添加一个ImageView然后再去设置它的背景图片和  那个边距的对其

 

6.更改Image的Stretching

 

7.最后去把ImageView 的各个边距都改一下 上 10   左 10    下 -10  右边  -15 最后跟新

 

8  重点----如何去根据label里面的文字的高度去自动计算那个文字的高度?????

1.实现它的给他添加了一个测试的数据源方法

9--重点----还有一个问题  怎么去更改的它的自动计算那个行高呢??????

cell的高度取决于label文字的高度和它的字体的大小决定的、

思想: 去获取那个cell里面的label的高度再去加上一个固定的高度就是cell的高度了

怎么去获取那个label的高度呢???

上面的额头像距上为5 加上那个上面label距离上面的10的高度 再加上label自己      的高度self.label.hight +下面的那个10,再去加上那个固定的高度就是cell的高度了

 

 

10.--重点----我们专门搞一个计算高度的属性(他是一个返回cell的方法,然后去返回cell高度的方法里面去给他完成一下赋值的操作,最后去实现)

  //还少了一步 ,一定要加上去设置那个label的数据

    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

    return [self.chatCellTool cellHeight];

 

 

/** 计算高度的cell的属性*/

 @property (nonatomic,strong)UXZYChatCell *chatCellTool;

 

   //给计算cell高度的对象完成一个赋值

    //他返回的是一个cell 这个cell只是在那个返回高度的方法里面去用到了,其他的地方没有用到

记得最好把它的方法static NSString *Indentifier = @"ReceiveCell";写在那个cell的.h文件中

tableview记得再拖一次线  为什么任何一个的Identifier:都可以呢?????

因为你在返回高度的方法里面都是一样的执行的,不获去细分你是哪一个cell的方法 so。。。

    self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:SenderCell];

 

 

--------------发送聊天消息---------------------

1.首先要做的是把那个 textView的发送框改成send属性 第四个选项里面的有一个

  Return Key 选项 改成那个Send选项

 

2.怎么去发送按钮的事件呢?????

1.把那个textView 的代理的线连上   2.然后去那个tableView里面的那个去遵守textView代理

 

在textView的方法里面去监听他最后的字符有没有换行,如果有换行的字符的话我就代表说他是发送sender的按钮]

 

3.怎么去发送文字呢???????

#pragma mark-UITextView的代理

-(void)textViewDidChange:(UITextView *)textView {

    if([textView.text hasSuffix:@"\n"] ) {

        NSLog(@"这是一个发送事件");

        //发送文字

        [self sendMessage:textView.text];

        

        //清空文字

        textView.text = nil;

    

    }

}

 

-(void)sendMessage:(NSString *)text {

    //创建一个消息对象实例

    EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:nil bodies:nil];

    //发送消息

    [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

        NSLog(@"消息准备发送");

    } onQueue:nil completion:^(EMMessage *message, EMError *error) {

        NSLog(@"消息完成发送");

    } onQueue:nil];

    

}

还缺少一个参数  就是把消息发送给谁? 我们就缺少一个参数传递

initWithReceiver:要去拿到那个参数好友列表的参数 EMBuddy 

#warning 每一种消息类型对象不同的消息体

    //EMTextMessageBody

    //EMVoiceMessageBody

    //EMVideoMessageBody

   // EMLocationMessageBody

   // EMImageMessageBody

    

    //创建一个聊天的文本对象

    EMChatText *chatText = [[EMChatText alloc]initWithText:text];

    //创建一个文本消息体

    EMTextMessageBody *textBody = [[EMTextMessageBody alloc]initWithChatObject:chatText];

    

    //创建一个消息对象实例   bodies是一个数组

    EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

    //发送消息

    

    [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

        NSLog(@"消息准备发送");

    } onQueue:nil completion:^(EMMessage *message, EMError *error) {

        NSLog(@"消息完成发送");

    } onQueue:nil];

 

注意点  : 加上一个return;去测试

把选中的好友列表正向传递进去

最后别忘了把那个return打开;

    

 

--------------显示好友的名字---------------------

1.在那个聊天的控制器的viewdidload里面写上

self.titlte = self.buddy.username

 

——————-------加载本地的聊天数据--------------------

有封装好的东西,先去内存的会话列表中去获取会话  如果没有找到就去数据库中去获取会话

没有找到就会出发现的会话

 

#pragma mark-加载本地的聊天数据 

-(void)loadLocalChatrecords {

    //获取本地聊天记录 会话对象

   EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.buddy.username conversationType: eConversationTypeChat];

    //加载当前来哦天用户所有的聊天记录

    NSArray *messages = [conversation loadAllMessages];

    

    for(id obj in messages) {

        NSLog(@"%@",[obj class]);

    }

    

    [self.dataSources addObject:messages];

    

}

 

  [self.dataSources addObject:messages];加上了就报错了,她的原因是什么呢?

  tableView:heightForRowAtIndexPath 错了

 

跳进设置高度的方法里面去 去吧里面改动一下

    //改进后的cell高度的获取

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

//    EMMessage *msg = self.dataSources[indexPath.row];

//    id body = msg.messageBodies[0];

//    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

//        EMTextMessageBody *textBody = body;

//        cell.messageLabel.text = textBody;

//    }

 

最后是用一个set方法去代替他们

 

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

    EMMessage *msg = self.dataSources[indexPath.row];

    //改进后的cell高度的获取

//    id body = msg.messageBodies[0];

//    

//    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

//        EMTextMessageBody *textBody = body;

//        cell.messageLabel.text = textBody;

//    }

    self.chatCellTool.message = msg;

    return [self.chatCellTool cellHeight];

    

    //还少了一步 ,一定要加上去设置那个label的数据

//    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

//    return [self.chatCellTool cellHeight];

}

最后别忘了去那个tableviewcell的模型里面去改,

 

————为了计算高度我们建立了一个模型——----------

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

     //改进后的cell高度的获取

    //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

    EMMessage *msg = self.dataSources[indexPath.row];

    

    self.chatCellTool.message = msg;

    

    return [self.chatCellTool cellHeight];

}

重写了模型的set方法 ,然后去调用了他的set方法

 

最后别忘了在显示的时候去调用他渲染那个方法

我的这个msg是一个消息模型

msg.messageBodies[0]

这样才能拿到消息体

msg.messageBodies[0].text才正确

 

-------------

[Pasted Graphic.tiff]

----------这样还不对-------------------------

 

你会看到你发出去的消息会在左边能看到

如何让它只能在右边显示呢??????????/

EMmessage有两个属性 from   to

from是发送方也就是自己    from是好友的话自己就是接受方

所以我们得在现实渲染的方法里面去先去获取消息模型

然后再去做一个from的判断

 

    UXZYChatCell *cell = nil;

    //先去获取消息模型然后去在去判断是发送方还是接收方

    EMMessage *msg = self.dataSources[indexPath.row];

    if([msg.from isEqualToString:self.buddy.username]) {//自己接收方

       cell = [tableView dequeueReusableCellWithIdentifier:Indentifier];

    }else {

       cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];

    }

 

--------怎么让你的消息立马显示-----------------------

去这个方法里面 

-(void)sendMessage:(NSString *)text { }

 

msgObj是你自己创建一个消息对象实例   bodies是一个数组

 EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

    //把消息添加到数据源 再刷新表格

    [self.dataSources addObject:msgObj];

    [self.tableView reloadData];

 

------怎么让你的消息自己滚动到最上面的一行----

   

    //4.把消息显示在顶部

    [self scrollToBottom];

}

 

-(void)scrollToBottom {

    //获取最后一行

    if(self.dataSources.count == 0){

        return;

    }

    NSIndexPath *lastIndex = [NSIndexPath indexPathForRow:self.dataSources.count-1 inSection:0];

    

    

    [self.tableView scrollToRowAtIndexPath:lastIndex atScrollPosition:UITableViewScrollPositionBottom animated:YES];

}

 

—————仔细的你到这一步了发没发现你那个你发出去的消息子啊框里面都会多出一行---

原因:是你在点击发送的时候他换了一下行,换行字符只展占用一个字节

如何去清除那个换行的字符,在发消息的放里面去实现

        text = [text substringToIndex:text.length-1];

 

 

-----------怎么去监听消息的回复--------------------

1.设置代理方法  并遵循它的 代理方法

2.有一个那个mesage的方法去实现一下

 

 

 

 

------对输入框的完善,即在你输入的时候那个输入框的高速会自动增加-------------------------

1.得定义输入框的一个最小的高度和最大的高度

2.textView是继承于UIscrollView   scrollView有一个属性 contensize 属性

    这个是计算那个做一个判断 不同情况下面的高度

 

3.我们再去拿到那个的InputView 的高度的约束  再去连线使它成为一个属性  然后像之前一样去约束它,找到他,然后给他连线 使它成为一个属性

 

    //获取contentsize的高度

    CGFloat contentHeight = textView.contentSize.height;

    if (contentHeight <minHeight) {

        textViewH = minHeight;

    }else if (contentHeight >maxHeight) {

        textViewH = maxHeight;

    }else {

        textViewH = contentHeight;

    }

    

    self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

 

4.还是有一个问题,就是在你输入完了一之后发送了   之后textView还是有一个换行的空格

所以还得有一个在发送完了后的判断语句

if([textView.text hasSuffix:@"\n"] ) {

        NSLog(@"这是一个发送事件");

        //发送文字

        [self sendMessage:textView.text];

        

        //清空文字

        textView.text = nil;

        

//        发送时textView的高速为最小的高度

        textViewH = minHeight;

    

    }

    self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

 

5.设置textView的背景图片  在SB中去设置 拖入一个IMageView 然后把它拿到那个textView的上面去   然后改透明  设置背景图片    把图片拉伸  streching  别忘了给背景图片加约束 不然的话他会随着那个的高度的增加他不会随着拉伸   最后去加个动画

 

6.——————---发送完了后发现光标不见了 发大模拟器看在左上角???

原因???scrollView有一个contentOffset.y的值会随着你的那个的光标的contensize的而向上拖动而拖送

NSStringFromCGSize(textView.contentSet)可以打印出来看看

contentOffset一开始为(0,0)之后它的y值为正数了,为什么呢,因为他要显示的下面的文字内容的话它的那个轴必须下移动 所以为正 

如何解决  哪次发送完了 让它的contentset恢复到原位

 

 

环信遇到的bug1:真机上面不能跑  模拟器可以

[Pasted Graphic_1.tiff]

 

把那个bitcode 设置为NO  bitcode是被编译程序的一种中间形式的代码。包含bitcode配置的程序将会在App store上被编译和链接

默认是yes   

 

 

storyboard作为控制器的复习

 

1.拖入一导航控制器 ,更改尺寸    去掉后一个

2.拖入一个viewControler  然后去把它的那个root viewcontroller  设置一下

 

3.创建一个控制器UIviewcontroller     第三个选项 class里面更改继承关系   

 

 

4.拖线 连线        1.去改掉main        2。去那个第4个 is initial  View Controller 的钩上

 

 

登录提供了三种方法

 

 

1.同步     2.block的异步      3.代理的回调

 

注释的方法提示在图表

方式一:/// 点在图标

方式二: 

 /*!

 *   @brief 点在图标

 */ 收起阅读 »

java集成环信

  1、项目环境描述
   项目是一个关于教育的项目,主要的架构是Spring,Struts2,Hibernate,前端页面是Jsp。
   手机端:Android,IOS
  2.项目需求描述
   项目中有一个需求是聊天的功能,主要有好友聊天,陌生人聊天,同班同学群聊三种。
  3.集成步骤
    1)、服务器集成文档
    http://docs.easemob.com/im/100 ... intro 
    
   
2.png


    在页面中点击"示例代码"栏中的“这里”
    2)、服务器端代码下载
    https://github.com/easemob/emchat-server-examples 

   
1.png


    在页面中选择对应的语言版本进行下载,本项目需要的是java版本emchat-server-java
    4)、将下载的代码引入项目中
     将libs下边的jar导入项目。
     将代码加入项目并调试不报错,主要注意配置文件中的内容。文件里内容有:
     API_PROTOCAL = https  //协议
     API_HOST = a1.easemob.com //ip
     API_ORG = 1193161011115832  //组织信息
     API_APP = testapp //应用名称
     APP_CLIENT_ID = YXA6Gj8v8KAIEea4-ukHSS2iNQ
     APP_CLIENT_SECRET = YXA6pSzVILsRgv9Wu2cRsVhJxoAz924
     上述参数要根据具体的环信应用得到
     5)、注册环信,登录后创建应用。应用的参数信息主要用于上述的配置文件中。
  4、应用步骤
     1)、分工
       服务器端负责注册/删除环信用户,推送系统消息。手机端负责登录,退出,消息管理。
     2)、数据库
       1、用户信息
         保存项目用户的基本注册信息,一般通过手机号进行注册,环信用户的用户名为手机号,密码和系统保持一致。保证手机端在登录系统后登录环信。保持统一在线。
       2、好友
          好友表中记录用户之间的关系,关系分为:发送好友请求,同意好友,拒绝好友,黑名单,陌生人。
     3)、服务封装
        1、登录时先查看用户是否注册环信IM用户,如果没有则先注册然后登录。
        2、删除用户时,查看是否注册IM用户,如果有则一起删除。
        3、退出时,通过环信的退出提醒在手机端提醒用户退出。
        4、添加好友,判断是否是好友,同时对黑名单进行处理。
        5、用户的头像,性别,名称等进本信息都是通过系统查询得到。
        6、好友列表,陌生人列表通过对好友表查询得到用户的具体信息,然后展示好友/陌生人列表信息
        7、同班同学是通过班级表来确认用户的班集体,进而查询得到所有同班同学的信息,展示同班同学列表。
        8、聊天时,直接向用户手机号的IM用户发送消息即可。
     项目只是用到了环信最基本的聊天功能,环信有更丰富的内容。比如:好友管理,上线下线管理,群聊,批量注册,手机端信息推送,环信客服等功能。
     跟多信息请到环信官网查询:http://www.easemob.com/

 
继续阅读 »
  1、项目环境描述
   项目是一个关于教育的项目,主要的架构是Spring,Struts2,Hibernate,前端页面是Jsp。
   手机端:Android,IOS
  2.项目需求描述
   项目中有一个需求是聊天的功能,主要有好友聊天,陌生人聊天,同班同学群聊三种。
  3.集成步骤
    1)、服务器集成文档
    http://docs.easemob.com/im/100 ... intro 
    
   
2.png


    在页面中点击"示例代码"栏中的“这里”
    2)、服务器端代码下载
    https://github.com/easemob/emchat-server-examples 

   
1.png


    在页面中选择对应的语言版本进行下载,本项目需要的是java版本emchat-server-java
    4)、将下载的代码引入项目中
     将libs下边的jar导入项目。
     将代码加入项目并调试不报错,主要注意配置文件中的内容。文件里内容有:
     API_PROTOCAL = https  //协议
     API_HOST = a1.easemob.com //ip
     API_ORG = 1193161011115832  //组织信息
     API_APP = testapp //应用名称
     APP_CLIENT_ID = YXA6Gj8v8KAIEea4-ukHSS2iNQ
     APP_CLIENT_SECRET = YXA6pSzVILsRgv9Wu2cRsVhJxoAz924
     上述参数要根据具体的环信应用得到
     5)、注册环信,登录后创建应用。应用的参数信息主要用于上述的配置文件中。
  4、应用步骤
     1)、分工
       服务器端负责注册/删除环信用户,推送系统消息。手机端负责登录,退出,消息管理。
     2)、数据库
       1、用户信息
         保存项目用户的基本注册信息,一般通过手机号进行注册,环信用户的用户名为手机号,密码和系统保持一致。保证手机端在登录系统后登录环信。保持统一在线。
       2、好友
          好友表中记录用户之间的关系,关系分为:发送好友请求,同意好友,拒绝好友,黑名单,陌生人。
     3)、服务封装
        1、登录时先查看用户是否注册环信IM用户,如果没有则先注册然后登录。
        2、删除用户时,查看是否注册IM用户,如果有则一起删除。
        3、退出时,通过环信的退出提醒在手机端提醒用户退出。
        4、添加好友,判断是否是好友,同时对黑名单进行处理。
        5、用户的头像,性别,名称等进本信息都是通过系统查询得到。
        6、好友列表,陌生人列表通过对好友表查询得到用户的具体信息,然后展示好友/陌生人列表信息
        7、同班同学是通过班级表来确认用户的班集体,进而查询得到所有同班同学的信息,展示同班同学列表。
        8、聊天时,直接向用户手机号的IM用户发送消息即可。
     项目只是用到了环信最基本的聊天功能,环信有更丰富的内容。比如:好友管理,上线下线管理,群聊,批量注册,手机端信息推送,环信客服等功能。
     跟多信息请到环信官网查询:http://www.easemob.com/

  收起阅读 »

iOS 端环信集成的使用

最近开发了一款社交类的APP,使用的环信的即时通讯功能!这个集成环信的SDK到应用中很简单,就是在使用过程中有点问题,自定义消息的接收列表!环信在聊天总对头像和昵称没做存贮,聊天的时候无法获取对方账号的个人信息,看Demo是存放在一个第三方的云了,通过账号实时的读取,感觉不是很好;我们的应用使用了环信的消息扩展,在扩展中添加发送消息方的昵称和头像,这样就可以实时获取对方的消息,也不用读取别的第三方了!最近在做自动建群和个人建群,做完后可以大家继续探讨!
继续阅读 »
最近开发了一款社交类的APP,使用的环信的即时通讯功能!这个集成环信的SDK到应用中很简单,就是在使用过程中有点问题,自定义消息的接收列表!环信在聊天总对头像和昵称没做存贮,聊天的时候无法获取对方账号的个人信息,看Demo是存放在一个第三方的云了,通过账号实时的读取,感觉不是很好;我们的应用使用了环信的消息扩展,在扩展中添加发送消息方的昵称和头像,这样就可以实时获取对方的消息,也不用读取别的第三方了!最近在做自动建群和个人建群,做完后可以大家继续探讨!
收起阅读 »

环信SDK3.0时遇到的问题及解决办法汇总

1.先直接根据官方文档集成SDK,在集成之前如果是第一次接触环信,建议备份工程.

注:官方下载的包里会有两个静态库,一个是包含实时语音的库,另一个则不包含,根据业务需求,记得删除掉一个库,直接move to trash就可以.切记要删除!否则在后边的步骤会报重复引用链接错误.

2.根据官方文档导入依赖库的时候,dylib后缀没有的直接用tbd就可以(Xcode 7之后改为tbd).

加入系统SDK依赖库:

        CoreMedia.framework

        AudioToolbox.framework

        AVFoundation.framework

        MobileCoreServices.framework

        ImageIO.framework

        SystemConfiguration.framework

        libc++.a

        libresolv.dylib

        libz.dylib

        libstdc++.6.0.9.dylib

        libsqlite3.dylib

        libHyphenateSDK.a

如果报错:"_iconv", referenced from: _avcodec_decode_subtitle2 in libHyphenateFullSDK.a(utils.o),则另外要加入libiconv.tbd依赖库.

官方依赖库导入之后编译,此处编译会遇到的坑: 

1).报重复引用静态库错误(没删官方两个静态库中的一个) 

2).报与-all_load 冲突错误 根据文档改为-ObjC即可  如果改为-ObjC还有错 可按照文档改为 -force_load

注:项目如果用了友盟分享,改为-force_load之后 会与友盟有冲突,具体原因也不清楚,项目直接crash在分享新浪微博,此处求解惑.  改为-ObjC即可

到此步骤直到编译没错的时候就说明导入SDK 配环境成功.

3.环信官方提供了easeUI这个快速集成单聊界面,在集成easeUI之前建议不要用cocoapods来集成,因为会报一些莫名的错误. 

集成easeUI:

1).将EaseUI工程下载下来之后,直接拖入EaseUI文件夹,EaseUIResource里面的Resource文件夹,export文件夹里的resource文件夹下的EaseUIResource.bundle 包,到工程中.

2).新建一个pch文件,设置好路径之后,在pch文件中添加引用:EaseUI-Prefix.pch 、ChatDemo-UI3.0-Prefix.pch 这两个pch中的代码. 

此时编译会报一个 NSObject + EaseMob类别错误 (该类别是2.0demo中的,根本没有用) 可以选择注释,或者直接删除该类别.将该类别注释掉之后,如果报更多的错误,错误定在NSString或其他系统类上,在你新建的pch文件里,你所包含的头文件开始加上: #ifdef __OBJC__   结尾处加上: #endif 如下图:450A4D8A-1D3D-463A-8012-D75920068558.png此时编译如果还报错并且错误定在NSLocalizedString, 在你的pch文件里添上如下宏:

#define NSEaseLocalizedString(key, comment) [[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"EaseUIResource"withExtension:@"bundle"]] localizedStringForKey:(key) value:@"" table:nil]




3).下载官方提供的ChatDemo-3.0 拖入demo中3rdparty文件夹,因EaseUI本身集成了几个常用三方库,因此会与工程中你所用的重复,此时编译会报错.本身所包含的常用三方如下:MBProgressHUD、VoiceConvert、MJRefresh、SDWebImage. 如果有冲突,切记删除ChatDemo中的三方库,然后改掉相关报错的代码.

此时编译如果还报错,错误为Setting文件夹下的BackUp类,直接删除掉或注释即可,该类用处不大.

至此,编译成功则EaseUI的集成也完毕了.




环信的EaseUI其实只是做到一个展示的作用,包括一些控件的布局,排版都没有处理,因此我们可以直接用ChatDemo3.0中的ChatViewController这个界面,附上集成视频地址:http://v.youku.com/v_show/id_X ... 1-5-0




好了,到此当你把ChatViewController也集成完毕,一个初步成型的单聊界面就出来了.ps:环信支持非好友之间的聊天,你只要知道对方的环信id即可.




那么你会疑问了,头像和昵称还没有搞定.因为环信服务器不存储用户的头像和昵称,因此需要你与自己app的服务器交互,聊天界面的头像和昵称在如下方法中修改:

- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message





如果因业务需求用到会话列表,官方并没有非常完善的文档,可以参考demo中的ConversationListViewController.
 
转自:http://docs.easemob.com/doku.php?id=im:start
继续阅读 »
1.先直接根据官方文档集成SDK,在集成之前如果是第一次接触环信,建议备份工程.

注:官方下载的包里会有两个静态库,一个是包含实时语音的库,另一个则不包含,根据业务需求,记得删除掉一个库,直接move to trash就可以.切记要删除!否则在后边的步骤会报重复引用链接错误.

2.根据官方文档导入依赖库的时候,dylib后缀没有的直接用tbd就可以(Xcode 7之后改为tbd).

加入系统SDK依赖库:

        CoreMedia.framework

        AudioToolbox.framework

        AVFoundation.framework

        MobileCoreServices.framework

        ImageIO.framework

        SystemConfiguration.framework

        libc++.a

        libresolv.dylib

        libz.dylib

        libstdc++.6.0.9.dylib

        libsqlite3.dylib

        libHyphenateSDK.a

如果报错:"_iconv", referenced from: _avcodec_decode_subtitle2 in libHyphenateFullSDK.a(utils.o),则另外要加入libiconv.tbd依赖库.

官方依赖库导入之后编译,此处编译会遇到的坑: 

1).报重复引用静态库错误(没删官方两个静态库中的一个) 

2).报与-all_load 冲突错误 根据文档改为-ObjC即可  如果改为-ObjC还有错 可按照文档改为 -force_load

注:项目如果用了友盟分享,改为-force_load之后 会与友盟有冲突,具体原因也不清楚,项目直接crash在分享新浪微博,此处求解惑.  改为-ObjC即可

到此步骤直到编译没错的时候就说明导入SDK 配环境成功.

3.环信官方提供了easeUI这个快速集成单聊界面,在集成easeUI之前建议不要用cocoapods来集成,因为会报一些莫名的错误. 

集成easeUI:

1).将EaseUI工程下载下来之后,直接拖入EaseUI文件夹,EaseUIResource里面的Resource文件夹,export文件夹里的resource文件夹下的EaseUIResource.bundle 包,到工程中.

2).新建一个pch文件,设置好路径之后,在pch文件中添加引用:EaseUI-Prefix.pch 、ChatDemo-UI3.0-Prefix.pch 这两个pch中的代码. 

此时编译会报一个 NSObject + EaseMob类别错误 (该类别是2.0demo中的,根本没有用) 可以选择注释,或者直接删除该类别.将该类别注释掉之后,如果报更多的错误,错误定在NSString或其他系统类上,在你新建的pch文件里,你所包含的头文件开始加上: #ifdef __OBJC__   结尾处加上: #endif 如下图:450A4D8A-1D3D-463A-8012-D75920068558.png此时编译如果还报错并且错误定在NSLocalizedString, 在你的pch文件里添上如下宏:

#define NSEaseLocalizedString(key, comment) [[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"EaseUIResource"withExtension:@"bundle"]] localizedStringForKey:(key) value:@"" table:nil]




3).下载官方提供的ChatDemo-3.0 拖入demo中3rdparty文件夹,因EaseUI本身集成了几个常用三方库,因此会与工程中你所用的重复,此时编译会报错.本身所包含的常用三方如下:MBProgressHUD、VoiceConvert、MJRefresh、SDWebImage. 如果有冲突,切记删除ChatDemo中的三方库,然后改掉相关报错的代码.

此时编译如果还报错,错误为Setting文件夹下的BackUp类,直接删除掉或注释即可,该类用处不大.

至此,编译成功则EaseUI的集成也完毕了.




环信的EaseUI其实只是做到一个展示的作用,包括一些控件的布局,排版都没有处理,因此我们可以直接用ChatDemo3.0中的ChatViewController这个界面,附上集成视频地址:http://v.youku.com/v_show/id_X ... 1-5-0




好了,到此当你把ChatViewController也集成完毕,一个初步成型的单聊界面就出来了.ps:环信支持非好友之间的聊天,你只要知道对方的环信id即可.




那么你会疑问了,头像和昵称还没有搞定.因为环信服务器不存储用户的头像和昵称,因此需要你与自己app的服务器交互,聊天界面的头像和昵称在如下方法中修改:

- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message





如果因业务需求用到会话列表,官方并没有非常完善的文档,可以参考demo中的ConversationListViewController.
 
转自:http://docs.easemob.com/doku.php?id=im:start 收起阅读 »

集成的单聊界面不能下拉加载更多的问题

只需要在EaseMessageViewController 的viewDidLoad方法里底部加上[self tableViewDidTriggerHeaderRefresh];即可解决。
祝环信越来越好!
只需要在EaseMessageViewController 的viewDidLoad方法里底部加上[self tableViewDidTriggerHeaderRefresh];即可解决。
祝环信越来越好!

环信receive的本地封装

使用环信一年多来,由于iOS环信的长链本地接收通过的是单例对象EaseMob的代理来实现的,但是由于OC中代理单一指向问题,导致多个使用环信的界面都需要设置代理,并且要在viewwillappear方法中设置,这样虽然能够实现需求,但很不友好。

最近在重构环信的本地封装,思路如下:
  1. 建立一个新的单例对象(该对象是EaseMob的Receive的进一步抽象)
  2. 新的单例对象是EaseMob单例的delegate
  3. 新的单例对象使用block来实现长链消息的本地handle
  4. 针对每一个接收代理方法建立private一个数组属性,每个数组的成员变量都是block(当delegate被调用,便利数组回执block)

 
经实测以上方法可行,并避免了在viewwillappear方法中加入冗余代码,影响效率。
继续阅读 »
使用环信一年多来,由于iOS环信的长链本地接收通过的是单例对象EaseMob的代理来实现的,但是由于OC中代理单一指向问题,导致多个使用环信的界面都需要设置代理,并且要在viewwillappear方法中设置,这样虽然能够实现需求,但很不友好。

最近在重构环信的本地封装,思路如下:
  1. 建立一个新的单例对象(该对象是EaseMob的Receive的进一步抽象)
  2. 新的单例对象是EaseMob单例的delegate
  3. 新的单例对象使用block来实现长链消息的本地handle
  4. 针对每一个接收代理方法建立private一个数组属性,每个数组的成员变量都是block(当delegate被调用,便利数组回执block)

 
经实测以上方法可行,并避免了在viewwillappear方法中加入冗余代码,影响效率。 收起阅读 »

环信小程序 Demo源码发布,集成视频手把手教你玩转小程序!

   1月9日,向乔布斯致敬的张小龙如约发布了微信小程序,首批上线的小程序就有300多家,一时刷爆朋友圈,如果不转发一两条有关小程序的内容,你都不好意思自称挨踢人。从效率看,小程序成功给APP瘦身,节省了系统资源。以往用户经常面临APP安装繁琐、加载缓慢、吃运存、占空间等痛点,有了小程序,这些问题可以迎刃而解,同时,几乎所有的API可以移植在小程序上,这在很大程度上节约了开发成本和时间,所以小程序的前期投入并不高。

   为了让大家的小程序都能顺利“聊”起来,环信小程序Demo源码也于今日正式发布,也许在“用完即走”基础上“聊两句再走”也是极好的哦!同时,环信工程师们还贴心的为大家准备好了集成使用教程视频,手把手教你玩转小程序。
 
  环信小程序运行视频在线观看

 微信小程序 Demo

环信准备了微信小程序 Demo,该 Demo 基于 Web IM SDK,并在其基础之上进行了修改。如果您想在您的微信小程序中添加即时通讯的功能,可以参考以下方式集成。 
 
小程序运行效果

未命名_meitu_0.jpg



Demo源码下载

GitHub下载地址:https://github.com/easemob/webim-weixin-xcx.git 

或者,执行如下命令: 
git clone https://github.com/easemob/webim-weixin-xcx.git
安装IDE

进入微信公众平台的官网下载“开发者工具”,并安装。目前支持 windows 64、windows 32、mac 版本。

 配置服务器地址

登录微信小程序账户,配置以下服务器地址:

使用微信小程序 Demo

使用“微信web开发者工具”打开微信小程序 Demo,步骤如下:
  1. 打开“微信web开发者工具”,使用微信扫一扫授权登录。
  2. 选择“本地小程序项目 → 添加项目”。
  3. 填写AppID、项目名称(自定义)、项目目录(本地代码路径),并点击“添加项目”。


进入“微信小程序Demo”项目后,可以对项目进行编辑、调试。 
 

 
继续阅读 »
   1月9日,向乔布斯致敬的张小龙如约发布了微信小程序,首批上线的小程序就有300多家,一时刷爆朋友圈,如果不转发一两条有关小程序的内容,你都不好意思自称挨踢人。从效率看,小程序成功给APP瘦身,节省了系统资源。以往用户经常面临APP安装繁琐、加载缓慢、吃运存、占空间等痛点,有了小程序,这些问题可以迎刃而解,同时,几乎所有的API可以移植在小程序上,这在很大程度上节约了开发成本和时间,所以小程序的前期投入并不高。

   为了让大家的小程序都能顺利“聊”起来,环信小程序Demo源码也于今日正式发布,也许在“用完即走”基础上“聊两句再走”也是极好的哦!同时,环信工程师们还贴心的为大家准备好了集成使用教程视频,手把手教你玩转小程序。
 
  环信小程序运行视频在线观看

 微信小程序 Demo

环信准备了微信小程序 Demo,该 Demo 基于 Web IM SDK,并在其基础之上进行了修改。如果您想在您的微信小程序中添加即时通讯的功能,可以参考以下方式集成。 
 
小程序运行效果

未命名_meitu_0.jpg



Demo源码下载

GitHub下载地址:https://github.com/easemob/webim-weixin-xcx.git 

或者,执行如下命令: 
git clone https://github.com/easemob/webim-weixin-xcx.git
安装IDE

进入微信公众平台的官网下载“开发者工具”,并安装。目前支持 windows 64、windows 32、mac 版本。

 配置服务器地址

登录微信小程序账户,配置以下服务器地址:

使用微信小程序 Demo

使用“微信web开发者工具”打开微信小程序 Demo,步骤如下:
  1. 打开“微信web开发者工具”,使用微信扫一扫授权登录。
  2. 选择“本地小程序项目 → 添加项目”。
  3. 填写AppID、项目名称(自定义)、项目目录(本地代码路径),并点击“添加项目”。


进入“微信小程序Demo”项目后,可以对项目进行编辑、调试。 
 

  收起阅读 »

感谢环信这么几年来的免费支持。

在开发过程中遇到的问题,环信客服都会耐心的回答,从刚入门时的小白,到现在的游刃有余。一直以来都有环信客服的陪伴。
祝愿环信早日上市,拥有美好的未来。
在开发过程中遇到的问题,环信客服都会耐心的回答,从刚入门时的小白,到现在的游刃有余。一直以来都有环信客服的陪伴。
祝愿环信早日上市,拥有美好的未来。

环信动态库sdk上架问题解决方案

环信发布了动态库sdk:
2639170-be3d6bfe875d544c.png

但是也会有一些问题,这里讲下关于这个上架的问题。

1.先把Hyphenate.framework放到桌面上;

2.终端位置cd到桌面;

3.运行:lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7  

4.运行后没有输出提示,直接运行下一个命令:lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64                                                                                                                                                                

5.运行后一样没有输出提示,直接运行下一个命令:lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate                                                                                                                                                                            

6.运行后一样没有输出提示,直接运行最后一个命令:mv Hyphenate Hyphenate.framework/
2639170-6aa66fdee8102250.png

得到的Hyphenate.framework就是最后的结果,拖进工程,编译打包上架。
 
作者:环信ios工程师张磊
继续阅读 »
环信发布了动态库sdk:
2639170-be3d6bfe875d544c.png

但是也会有一些问题,这里讲下关于这个上架的问题。

1.先把Hyphenate.framework放到桌面上;

2.终端位置cd到桌面;

3.运行:lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7  

4.运行后没有输出提示,直接运行下一个命令:lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64                                                                                                                                                                

5.运行后一样没有输出提示,直接运行下一个命令:lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate                                                                                                                                                                            

6.运行后一样没有输出提示,直接运行最后一个命令:mv Hyphenate Hyphenate.framework/
2639170-6aa66fdee8102250.png

得到的Hyphenate.framework就是最后的结果,拖进工程,编译打包上架。
 
作者:环信ios工程师张磊 收起阅读 »

Web IM V1.4.8已发布,刷新页面保持登陆状态


9153.jpg_wh860_.jpg

新功能:


[demo] 增加webrtc视频聊天的声音开关
[demo] 动态创建chatWindow,提高网页性能
[demo] 切换leftbar时会给chatWindow添加遮罩,返回之前的leftbar时会直接跳到之前选中的cate和chatWindow
[demo] 登录成功后,刷新页面不会再回到登录页



Bug修复:


[sdk] 移除sdk中所有log方法
[sdk] 退出muc group room 时,追加发送一条unavailable的presence stanza



webim体验:https://webim.easemob.com/ 

版本历史:更新日志
 
SDK下载:点击下载
继续阅读 »

9153.jpg_wh860_.jpg

新功能:


[demo] 增加webrtc视频聊天的声音开关
[demo] 动态创建chatWindow,提高网页性能
[demo] 切换leftbar时会给chatWindow添加遮罩,返回之前的leftbar时会直接跳到之前选中的cate和chatWindow
[demo] 登录成功后,刷新页面不会再回到登录页



Bug修复:


[sdk] 移除sdk中所有log方法
[sdk] 退出muc group room 时,追加发送一条unavailable的presence stanza



webim体验:https://webim.easemob.com/ 

版本历史:更新日志
 
SDK下载:点击下载 收起阅读 »

数据驱动下的在线旅游新生态——易观数聚论(旅游专场)

   2016年中国在线度假旅游市场目前处于市场高速发展阶段。

   纵观2016年中国的在线度假旅游的市场发展状况;线上线下融合程度提升。2016年中国在线度假旅游市场竞争向全产业链深入,在线度假旅游企业对资源端的渗透能力和用户细分需求的精细化响应是市场竞争核心,行业整合将向产业链上游不断深入;同时线下旅游企业对于互联网平台重视程度提升,线上线下企业通过战略合作、投资入股等方式加强资源端与渠道端协同,出现海航与途牛联姻、众信与携程联姻、万达与同程联姻等案例,说明市场整合不断深入,线上线下一体化加速,互联网正成为串联渠道和资源等产业链多环节的基础平台。

   1月14日,易观邀您一起探讨在线旅游市场在大数据的驱动下将如何完成2017年的新突破。   

 
▎活动背景

   “易观数聚论”是面向互联网+垂直领域关于大数据应用相关内容的线下研讨会。旨在为企业衡量数字用户资产价值,产品精细化运营,用户转化与变现等问题。

   “易观数聚论”将嘉宾架构更新为 “1位易观产品规划师+1位垂直领域知名企业领袖分享+2位该领域有实战案例嘉宾分享+话题互动”的模式,为互联网企业和在职人员提供相关领域的大数据应用干货。

   用户运营将成为所有类型企业的核心命题,如何进行数字用户资产管理和经营,是企业未来最重要的竞争力之一。数字用户资产四大价值,市值管理(企业第四张表)、获客、提高忠诚度、提供用户ARPU交相辉映,方法论倾囊相授,企业实践案例分析解读,一站式融会贯通数字用户资产运营方法论,学会经营用户。

   数据是新能源,易观是加油站。面对行业的机遇和挑战,易观将助力企业学习用户数字资产管理方法,提高用户转化与精准变现。

 

▎活动信息

时间:2017.1.14(周六)13:30-16:00

规模:100人(现场座位有限,按照报名顺序安排留座)

地点:上海市静安区愚园东路20号东海广场3号楼(具体地址电话/短信告知)

 

▎报名须知 

   为保证参会人员质量与留座到场率,本次活动为收费形式;报名者可在1月10日之前通过本平台购买“早鸟票”(单人:68元;套票双人:88元);1月10日之后即恢复原价100元/人。报名后凭审核短信签到入场,未报名者一概不予进场。以此带来不便,敬请谅解!

   注:活动无任何盈利目的,报名参会者可现场领取Linckia现磨咖啡一杯(大杯,种类可选)。




▎联系方式

活动联系人:许宏运 13120751039


▎活动详情
嘉宾介绍.jpeg

▎活动议程

13:30-13:55——签到

13:55-14:00——主持人开场

14:00-14:30——主题:中国在线旅游行业发展现状与趋势预测

        ——嘉宾:易观旅游行业中心资深分析师姜昕蔚

14:30-15:00——主题:旅游产品的用户转化与价值变现

        ——嘉宾:驴妈妈旅游网CMO黄春香 

15:00-15:30——主题:个性化定制旅行产品的新风口              

        ——嘉宾:指南猫创始人兼CEO任静

15:30-16:00——圆桌:旅游企业的新风口与新生态

16:00-16:20——交流/提问                                  

(提问者有机会获得价值880元的《互联网产业发展年鉴》一本)

                         

▎合作单位
主办.jpg

合作伙伴.jpg

——感谢以上平台对本次活动的大力支持!


▎往期回顾
往期回顾.jpg

 
我要报名:http://www.huodongxing.com/event/4368713124800
继续阅读 »
   2016年中国在线度假旅游市场目前处于市场高速发展阶段。

   纵观2016年中国的在线度假旅游的市场发展状况;线上线下融合程度提升。2016年中国在线度假旅游市场竞争向全产业链深入,在线度假旅游企业对资源端的渗透能力和用户细分需求的精细化响应是市场竞争核心,行业整合将向产业链上游不断深入;同时线下旅游企业对于互联网平台重视程度提升,线上线下企业通过战略合作、投资入股等方式加强资源端与渠道端协同,出现海航与途牛联姻、众信与携程联姻、万达与同程联姻等案例,说明市场整合不断深入,线上线下一体化加速,互联网正成为串联渠道和资源等产业链多环节的基础平台。

   1月14日,易观邀您一起探讨在线旅游市场在大数据的驱动下将如何完成2017年的新突破。   

 
▎活动背景

   “易观数聚论”是面向互联网+垂直领域关于大数据应用相关内容的线下研讨会。旨在为企业衡量数字用户资产价值,产品精细化运营,用户转化与变现等问题。

   “易观数聚论”将嘉宾架构更新为 “1位易观产品规划师+1位垂直领域知名企业领袖分享+2位该领域有实战案例嘉宾分享+话题互动”的模式,为互联网企业和在职人员提供相关领域的大数据应用干货。

   用户运营将成为所有类型企业的核心命题,如何进行数字用户资产管理和经营,是企业未来最重要的竞争力之一。数字用户资产四大价值,市值管理(企业第四张表)、获客、提高忠诚度、提供用户ARPU交相辉映,方法论倾囊相授,企业实践案例分析解读,一站式融会贯通数字用户资产运营方法论,学会经营用户。

   数据是新能源,易观是加油站。面对行业的机遇和挑战,易观将助力企业学习用户数字资产管理方法,提高用户转化与精准变现。

 

▎活动信息

时间:2017.1.14(周六)13:30-16:00

规模:100人(现场座位有限,按照报名顺序安排留座)

地点:上海市静安区愚园东路20号东海广场3号楼(具体地址电话/短信告知)

 

▎报名须知 

   为保证参会人员质量与留座到场率,本次活动为收费形式;报名者可在1月10日之前通过本平台购买“早鸟票”(单人:68元;套票双人:88元);1月10日之后即恢复原价100元/人。报名后凭审核短信签到入场,未报名者一概不予进场。以此带来不便,敬请谅解!

   注:活动无任何盈利目的,报名参会者可现场领取Linckia现磨咖啡一杯(大杯,种类可选)。




▎联系方式

活动联系人:许宏运 13120751039


▎活动详情
嘉宾介绍.jpeg

▎活动议程

13:30-13:55——签到

13:55-14:00——主持人开场

14:00-14:30——主题:中国在线旅游行业发展现状与趋势预测

        ——嘉宾:易观旅游行业中心资深分析师姜昕蔚

14:30-15:00——主题:旅游产品的用户转化与价值变现

        ——嘉宾:驴妈妈旅游网CMO黄春香 

15:00-15:30——主题:个性化定制旅行产品的新风口              

        ——嘉宾:指南猫创始人兼CEO任静

15:30-16:00——圆桌:旅游企业的新风口与新生态

16:00-16:20——交流/提问                                  

(提问者有机会获得价值880元的《互联网产业发展年鉴》一本)

                         

▎合作单位
主办.jpg

合作伙伴.jpg

——感谢以上平台对本次活动的大力支持!


▎往期回顾
往期回顾.jpg

 
我要报名:http://www.huodongxing.com/event/4368713124800 收起阅读 »

我要回归了

换了一份工作,需要使用即时通讯,那就比较尴尬了,我就直接确定环信了,毕竟老客户了^_^
换了一份工作,需要使用即时通讯,那就比较尴尬了,我就直接确定环信了,毕竟老客户了^_^