设置头像

设置头像

12
回复

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

xiaoyan2015 回复了问题 • 13 人关注 • 13141 次浏览 • 2019-01-14 10:04 • 来自相关话题

4
评论

【开源项目】全国首个开源直播小程序源码 环信公开课 小程序 直播

beyond 发表了文章 • 9361 次浏览 • 2018-07-20 17:30 • 来自相关话题

今天你看直播了吗?拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 





作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载


小程序直播demo_2018-06-21.zip







直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 




2、导入源码:将附件的源码解压直接导入 







环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]




填写对相关信息进行注册





注册成功后进行登录




注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用




输入应用名称等信息
 





创建成功后点击应用进入





需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量




3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Tokencurl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'返回格式{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址curl -X POST -H "Authorization: Bearer [管理员Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"成功返回格式:{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户





点击注册IM用户





填写用户信息





创建用户的过程同样也可以通过REST API形式进行curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'
注:应用必须为开放注册





将注册的用户添加为主播curl -X POST -H "Authorization: [管理员Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'返回结果示例:{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播





点击新建房间





填写房间信息




创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件





修改appkey为自己应用的appkey





打开pages/live/index.js修改房间默认拉流地址及直播间房间号





四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:curl -X GET -H "Authorization: Bearer [用户Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]
响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。 查看全部
今天你看直播了吗?
拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 
微信图片_20180725162426.jpg


作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载



预览图.jpg

直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 
Catch9A07(07-20-17-38-30).jpg

2、导入源码:将附件的源码解压直接导入 


Catch1C69(07-20-17-38-30).jpg


环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]
1.png

填写对相关信息进行注册

2.png

注册成功后进行登录
3.png

注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用
4.png

输入应用名称等信息
 

5.png

创建成功后点击应用进入

6.png

需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量
7.png

3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Token
curl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'
返回格式
{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址
curl -X POST -H "Authorization: Bearer [管理员Token]"  " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"
成功返回格式:
{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户

8.png

点击注册IM用户

9.png

填写用户信息

10.png

创建用户的过程同样也可以通过REST API形式进行
curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'

注:应用必须为开放注册

11.png

将注册的用户添加为主播
curl -X POST -H "Authorization: [管理员Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'
返回结果示例:
{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播

12.png

点击新建房间

13.png

填写房间信息
14.png

创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件

15.png

修改appkey为自己应用的appkey

16.png

打开pages/live/index.js修改房间默认拉流地址及直播间房间号

17.png

四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:
curl -X GET -H "Authorization: Bearer  [用户Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]

响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:
curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"
响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。
19
评论

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

dujiepeng 发表了文章 • 19673 次浏览 • 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...小伙伴们还有什么想知道欢迎跟帖提出。
 
3
评论

草草们的忧伤:环信IM昵称和头像 头像 昵称 扩展 头像 设置头像

江南孤鹜 发表了文章 • 12318 次浏览 • 2016-11-08 09:35 • 来自相关话题

最近天气转冷了,写篇文章,给大家暖暖心~





 
在环信草草群(群号:340452063)中,无论是安卓还是IOS或者WebIM,每天遇到最多的问题就是“如何显示昵称和头像”,鉴于大家的墙裂需求,所以我最近花了点时间研究了相关解决方案,希望能跟大家一起探索。
 
运行效果




 
目标
集成环信IM的SDK后,能以最快方式,最少代码管理用户的昵称和头像。
 
解决方案
使用本地缓存(sqlite)和后端云实现头像和昵称的二级缓存
【参考】 http://docs.easemob.com/im/490integrationcases/10nickname#昵称和头像的显示与更新
 
计划
先在IOS上验证该方案的优缺点,待方案完善后,再将此模式复制到Android和WebIM上

项目快速集成
1. 按照简版Demo的方式在项目中快速集成环信IM功能

IOS快速集成环信IM - 基于官方的Demo优化,5分钟集成环信IM功能http://www.imgeek.org/article/825307886

2. 注册第三方后端云账号,使用数据存储服务





(1). 在第三方后端注册用户,进入控制台,创建应用(例如名称为【环信简版Demo】),点击【存储】按钮进入数据存储管理页面:




 
(2). 创建数据表UserWebInfo,并且按照新增三个字段(字段名开头必须小写):openId String 环信ID
nickName String 用户昵称
avatarUrl String 用户头像(绝对路径)



 
其中,avatarUrl是app端上传头像到【_File】数据表后获取到的绝对路径:





(3). 在【设置】-> 【应用Key】页面中




复制AppID和AppKey替换AppDelagate里didFinishLaunchingWithOptions的key:// 初始化web缓存配置
[UserWebManager config:launchOptions
appId:@"utUG5ot9Y64dqJIFG9Ir2rqu-gzGzoHsz"
appKey:@"IbHhNkPo4gfrFFc3epCw3eG2"];参考: 简版demo中的AppDelegate+EaseMob.m第56行
 
3. 上传用户头像和昵称到第三方后端云服务器

用户在app中调用开发者服务器API接口登录成功后,一般都会返回用户的属性信息(昵称和头像等),我们可以在这里上传用户信息到云服务器:// 登录成功后,如果后端云没有缓存用户信息,则新增一个用户
[UserWebManager createUser:username nickName:nickName avatarUrl:avatarUrl];参考:简版demo中LoginViewController.m的第156行代码
 
4.显示用户昵称和头像

在需要显示用户昵称和头像的地方,调用UserCacheManager里的方法即可,具体调用地方,请在xcode里搜索简版Demo代码“[UserCacheManager ”,如图所示,在这里就不累赘了:




 
5.修改用户昵称和头像
(1). 更改头像// 上传头像到后端云
[UserWebManager updateCurrAvatar:orgImage completed:^(UIImage *imageData) {
[weakSelf hideHud];
if(!imageData){
[self showHint:@"更新头像失败~"];
return;
}

[weakSelf.headImageView imageWithUsername:kCurrEaseUserId placeholderImage:imageData];
[self showHint:@"更新头像成功~"];
}];参考简版Demo中UserProfileEditViewController.m第181行代码
 
(2). 更新昵称[UserWebManager updateCurrNick:@"小草" completed:^(BOOL isSucc) {
if (weakSelf) {
UserProfileEditViewController *strongSelf = weakSelf;
[strongSelf hideHud];
if (isSucc) {
[strongSelf.tableView reloadData];
[strongSelf showHint:@"修改成功~"];
} else {
[strongSelf showHint:@"修改失败~" yOffset:0];
}
}
}];参考简版Demo中UserProfileEditViewController.m第152行代码
 
6.二级缓存处理流程图





 
由于能力有限,此方案难免有不妥之处,欢迎大家拍砖。





环信互帮互助-非官方 340452063
 
Q&A

问:如何安装第三方后端云存储服务 SDK?

答:安装还是比较简单的,可以参考第三方的文档,有不明白的可以看下教程 

问:使用第三方云存储服务是否稳定、安全,比如不久他关闭了app会不会受影响?

答:云服务厂商一般不会关闭,退一万步来说,即使第三方后端云停止服务了也会提前通知,我们也可以将接口换成我们开发者自己服务器的api。类似的第三方云存储服务还有MaxLeap、bmob。
 
 
 
 
 
  查看全部
最近天气转冷了,写篇文章,给大家暖暖心~

1.png

 
在环信草草群(群号:340452063)中,无论是安卓还是IOS或者WebIM,每天遇到最多的问题就是“如何显示昵称和头像”,鉴于大家的墙裂需求,所以我最近花了点时间研究了相关解决方案,希望能跟大家一起探索。
 
运行效果
2.png

 
目标
集成环信IM的SDK后,能以最快方式,最少代码管理用户的昵称和头像。
 
解决方案
使用本地缓存(sqlite)和后端云实现头像和昵称的二级缓存
【参考】 http://docs.easemob.com/im/490integrationcases/10nickname#昵称和头像的显示与更新
 
计划
先在IOS上验证该方案的优缺点,待方案完善后,再将此模式复制到Android和WebIM上

项目快速集成
1. 按照简版Demo的方式在项目中快速集成环信IM功能

IOS快速集成环信IM - 基于官方的Demo优化,5分钟集成环信IM功能http://www.imgeek.org/article/825307886

2. 注册第三方后端云账号,使用数据存储服务

3.png

(1). 在第三方后端注册用户,进入控制台,创建应用(例如名称为【环信简版Demo】),点击【存储】按钮进入数据存储管理页面:
4.png

 
(2). 创建数据表UserWebInfo,并且按照新增三个字段(字段名开头必须小写):
openId   String   环信ID
nickName String 用户昵称
avatarUrl String 用户头像(绝对路径)
5.png

 
其中,avatarUrl是app端上传头像到【_File】数据表后获取到的绝对路径:

6.png

(3). 在【设置】-> 【应用Key】页面中
7.png

复制AppID和AppKey替换AppDelagate里didFinishLaunchingWithOptions的key:
// 初始化web缓存配置
[UserWebManager config:launchOptions
appId:@"utUG5ot9Y64dqJIFG9Ir2rqu-gzGzoHsz"
appKey:@"IbHhNkPo4gfrFFc3epCw3eG2"];
参考: 简版demo中的AppDelegate+EaseMob.m第56行
 
3. 上传用户头像和昵称到第三方后端云服务器

用户在app中调用开发者服务器API接口登录成功后,一般都会返回用户的属性信息(昵称和头像等),我们可以在这里上传用户信息到云服务器:
// 登录成功后,如果后端云没有缓存用户信息,则新增一个用户
[UserWebManager createUser:username nickName:nickName avatarUrl:avatarUrl];
参考:简版demo中LoginViewController.m的第156行代码
 
4.显示用户昵称和头像

在需要显示用户昵称和头像的地方,调用UserCacheManager里的方法即可,具体调用地方,请在xcode里搜索简版Demo代码“[UserCacheManager ”,如图所示,在这里就不累赘了:
8.png

 
5.修改用户昵称和头像
(1). 更改头像
// 上传头像到后端云
[UserWebManager updateCurrAvatar:orgImage completed:^(UIImage *imageData) {
[weakSelf hideHud];
if(!imageData){
[self showHint:@"更新头像失败~"];
return;
}

[weakSelf.headImageView imageWithUsername:kCurrEaseUserId placeholderImage:imageData];
[self showHint:@"更新头像成功~"];
}];
参考简版Demo中UserProfileEditViewController.m第181行代码
 
(2). 更新昵称
[UserWebManager updateCurrNick:@"小草" completed:^(BOOL isSucc) {
if (weakSelf) {
UserProfileEditViewController *strongSelf = weakSelf;
[strongSelf hideHud];
if (isSucc) {
[strongSelf.tableView reloadData];
[strongSelf showHint:@"修改成功~"];
} else {
[strongSelf showHint:@"修改失败~" yOffset:0];
}
}
}];
参考简版Demo中UserProfileEditViewController.m第152行代码
 
6.二级缓存处理流程图

9.png

 
由于能力有限,此方案难免有不妥之处,欢迎大家拍砖。

10.png

环信互帮互助-非官方 340452063
 
Q&A

问:如何安装第三方后端云存储服务 SDK?

答:安装还是比较简单的,可以参考第三方的文档,有不明白的可以看下教程 

问:使用第三方云存储服务是否稳定、安全,比如不久他关闭了app会不会受影响?

答:云服务厂商一般不会关闭,退一万步来说,即使第三方后端云停止服务了也会提前通知,我们也可以将接口换成我们开发者自己服务器的api。类似的第三方云存储服务还有MaxLeap、bmob。
 
 
 
 
 
 
2
回复

android 3.X 设置头像 设置头像

李。 回复了问题 • 2 人关注 • 1114 次浏览 • 2016-10-25 16:08 • 来自相关话题

18
评论

【环信集成笔记】进阶篇-android环信昵称头像解决方法 头像和昵称 环信集成 环信_Android 头像 设置头像

陈日明 发表了文章 • 6206 次浏览 • 2016-09-27 18:43 • 来自相关话题

当你刚刚集成环信的时候,在和自己android组的小伙伴玩的不亦乐乎的时候,当你过完这把瘾的时候,那么接下来,你就要考虑的是怎么让这个头像显示的是自己想要的头像,怎么让昵称显示自己的昵称.....

那么接下来,我来告诉大家,怎么解决昵称头像的问题,

首先,这篇文章是接在我大表哥江南孤鹜在im社区写的一篇文章之后写的,上个链接地址 Android获取昵称头像接下来,我对此文章做些补充:

我看到有些人在问,这个方法放在哪里?





好吧,大表哥没说出来,这个放在UserApiModel里面

那么接下来,大表哥写的是这样的,利用扩展消息去获取头像昵称,在这里我提醒下大家,要判断这个头像是自己的还是好友的




怎么判断呢,作为新手的我们,我推荐使用shareprefences在登陆的时候保存下自己的头像昵称,然后再这里获取,并且设置给扩展





在demohelper里面有个getuserinfo方法




这里就是把获取到的头像昵称设置给环信,然后显示出来,这里最重要,切记不要写错。

那么,到此为止,其实都说完了,可是,毕竟是一个延伸,怎么可能就此结束,接下来给大家看下,请求数据,然后设置给数据库





请求的过程我就不写了,这个大家都会,获取到username,id,logo,之后先要把头像,昵称存到userdao里面,如果userdao是环信的一个数据库,这个大家自己看看demo的代码就知道了,设置到这里,是为了在联系人列表里面显示,UserInfoCacheSvc.createOrUpdate(id,username,logo_img);这句就是把头像昵称放到大表哥写的数据库里面

最后,补充一下,忘记说了,导入框架




好了,这样就结束了,如果有什么还不明白,就加入大表哥粉丝群(环信IM互帮互助群 340452063),我会帮你解答一切问题 查看全部
当你刚刚集成环信的时候,在和自己android组的小伙伴玩的不亦乐乎的时候,当你过完这把瘾的时候,那么接下来,你就要考虑的是怎么让这个头像显示的是自己想要的头像,怎么让昵称显示自己的昵称.....

那么接下来,我来告诉大家,怎么解决昵称头像的问题,

首先,这篇文章是接在我大表哥江南孤鹜在im社区写的一篇文章之后写的,上个链接地址 Android获取昵称头像接下来,我对此文章做些补充:

我看到有些人在问,这个方法放在哪里?

1.png

好吧,大表哥没说出来,这个放在UserApiModel里面

那么接下来,大表哥写的是这样的,利用扩展消息去获取头像昵称,在这里我提醒下大家,要判断这个头像是自己的还是好友的
2.png

怎么判断呢,作为新手的我们,我推荐使用shareprefences在登陆的时候保存下自己的头像昵称,然后再这里获取,并且设置给扩展

3.png

在demohelper里面有个getuserinfo方法
4.png

这里就是把获取到的头像昵称设置给环信,然后显示出来,这里最重要,切记不要写错。

那么,到此为止,其实都说完了,可是,毕竟是一个延伸,怎么可能就此结束,接下来给大家看下,请求数据,然后设置给数据库

5.png

请求的过程我就不写了,这个大家都会,获取到username,id,logo,之后先要把头像,昵称存到userdao里面,如果userdao是环信的一个数据库,这个大家自己看看demo的代码就知道了,设置到这里,是为了在联系人列表里面显示,UserInfoCacheSvc.createOrUpdate(id,username,logo_img);这句就是把头像昵称放到大表哥写的数据库里面

最后,补充一下,忘记说了,导入框架
6.png

好了,这样就结束了,如果有什么还不明白,就加入大表哥粉丝群(环信IM互帮互助群 340452063),我会帮你解答一切问题
1
回复

android 3.X 设置聊天里自己的头像 设置头像

Wxin 回复了问题 • 2 人关注 • 1160 次浏览 • 2016-09-26 19:08 • 来自相关话题

18
评论

环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)。 头像 设置头像 头像和昵称 昵称 环信头像和昵称设置

zqbemail 发表了文章 • 12461 次浏览 • 2016-06-13 16:44 • 来自相关话题

        最近,经常有朋友问到,如何集成环信头像,怎么才能快速显示头像,因时间紧急,很多朋友都没有时间慢慢的研究代码,这里大家稍微花10分钟看一下文章,看完后再花5分钟改一下代码,即可达到你们所要的效果。
        当然这个是在你直接复制了demo中的工具类和必要的UI的前提下实现的。简短说明简单暴力的方法:除UI外的其他所有类先复制到自己工程中,UI部分MainActivity中的代码需要一个一个复制过去,如与自己项目冲突的需要调整,然后ChatActivity/ChatFragment也复制过去,这就可以进行聊天了。不过头像就是大家所遇到的头像显示不了,昵称显示为环信号码。
        环信官方是有给出头像的设置的,不过大部分朋友看了之后都是晕呼呼的。官方给出的提示如下:方法一 从APP服务器获取昵称和头像
昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求

昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二 从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像URI与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
---------------------------------------------------------------------------------------------
        个人推荐使用方法2,优势比较明显,不仅可以设置头像、昵称,甚至以后出现的是否管理员,或者自己APP中的身份标志,如:店小二、医生、客服等等都可以再定义注明,暴力而简单,不需要考虑对方更新头像或昵称,而软件没重启的情况下怎么去更新头像和昵称等等复杂的问题。本指导以最简单的集成为指导,工具类可使用自己软件中的,或通过别的方式实现。
        方法2的集成步骤:
1、在登录的时候,把自己登录成功时后台返回的信息保存到sharedpreferences中,需要包含需要的头像和昵称。new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().login(username, password, new EMCallBack() {
@Override
public void onSuccess() {
// 登陆成功,保存用户昵称与头像URL
AppSPUtils.setValueToPrefrences("name", loginBean.getName());
AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl());

// 将自己服务器返回的环信账号、昵称和头像URL设置到帮助类中。
DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName());
DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl());
DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 环信Id

// ------以下参考demo中的,加载群组和加载消息。然后跳转到首页-------2、AppSPUtils是个人写的一个工具类,大家可以自己写一个,给出参考代码。public class AppSPUtils {

private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS;

public static SharedPreferences getSharedPreferences(String name) {
return MainApplication.getContext().getSharedPreferences(name,
Context.MODE_PRIVATE | MODE_SPEC);
}

public static SharedPreferences getAppSharedPreferences() {
return getSharedPreferences(Constants.SP_APP);
}

public static String getValueFromPrefrences(String key, String defaultValue) {
return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue);
}

public static void setValueToPrefrences(String key, String value) {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != preferences) {
preferences.edit().putString(key, value).commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 退出登录时要调用
public static void clean() {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != getAppSharedPreferences()) {
getAppSharedPreferences().edit().clear().commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}3、保存好自己的信息后,已经成功了四分之一,现在是如何将自己的头像昵称等信息发送出去,最简单的就是使用扩展消息了,在ChatActivity中可以看到,基本上只做了一件事,保证只有一个ChatActivity,那我们的代码在哪里?就在ChatFragment里面。找到代码,可以看到其实它是继承自EaseChatFragment,很多内容在easeui中已经做好了。
这时你会发现ChatFragment类中有一个扩展属性的说明,没错,就是这个方法,把你要发送的内容尽情的发送吧,现附上发送头像和昵称的代码:@Override
public void onSetMessageAttributes(EMMessage message) {
if (isRobot) {
// 设置消息扩展属性
message.setAttribute("em_robot_message", isRobot);
}

// 通过扩展属性,将userPic和userName发送出去。
String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute("userPic", userPic);
}
String userName = AppSPUtils.getValueFromPrefrences("name", "");
if (!TextUtils.isEmpty(userName)) {
message.setAttribute("userName", userName);
}
}4、发送完成,你已经完成了四分之二的任务了。发送完成后,肯定需要一个接收,其实demo中的广播已经接收好了,那么我们跟随着广播的脚步,来到DemoHelper这个类,初次看这个类,都是云一样的感觉,经过一番查找,发现有个onMessageReceived的方法,并且还有注释“全局监听”,赶紧开工,试试接收吧,可以自己打一下log出来看是不是拿到了我们要的。并且照着demoHelper中的保存方法,将接收到的内容保存起来。@Override
public void onMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
message.setMsgTime(System.currentTimeMillis());
//************接收并处理扩展消息***********************
String userName = message.getStringAttribute("userName", "");
String userPic = message.getStringAttribute("userPic", "");
String hxIdFrom = message.getFrom();
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(userName);

// 存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
// 存入db
UserDao dao = new UserDao(MainApplication.getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.add(easeUser);
dao.saveContactList(users);

getModel().setContactSynced(true);

// 通知listeners联系人同步完毕
notifyContactsSyncListener(true);
if (isGroupsSyncedWithServer()) {
notifyForRecevingEvents();
}

// ******************扩展信息处理完成**********************
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
// 应用在后台,不需要刷新UI,通知栏提示新消息
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}5、信息都收到了,就差最后一步就可以显示了,不知道你们是不是激动,反正我是激动了。那在哪里进行显示呢?还是在DemoHelper中,找到getUserInfo方法,代码如下:private EaseUser getUserInfo(String hxId) {
// 获取user信息,demo是从内存的好友列表里获取,
// 实际开发中,可能还需要从服务器获取用户信息,
// 从服务器获取的数据,最好缓存起来,避免频繁的网络请求

if (hxId.equals(EMClient.getInstance().getCurrentUser())) {
EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo();
return currentUserInfo;
}
EaseUser easeUser;
if (contactList != null && contactList.containsKey(hxId)) {

} else { // 如果内存中没有,则将本地数据库中的取出到内存中。
getContactList();
}
// // TODO 获取不在好友列表里的群成员具体信息,即陌生人信息,demo未实现
// if (user == null && getRobotList() != null) {
// user = getRobotList().get(hxId);
// }
easeUser = contactList.get(hxId);
if(easeUser == null){
easeUser = new EaseUser(hxId);
} else {
if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字为空,则显示环信号码
easeUser.setNick(easeUser.getUsername());
}
}
return easeUser;
}OK,大功告成,到这里你的头像已经可以显示了。。恭喜你!
有朋友还有疑问,为什么头像是方形的,要变成圆形怎么办?指个路,在easeui中的utils包下,找到EaseUserUtils,这里就是显示用户头像和用户昵称的地方,通过Glide可以轻松显示圆形头像,百度有很多方法,这里就不多讲了,同样,你也可以通过其他图形加载框架来完成。
很多朋友不明白扩展消息的是什么东西,也不明白为什么照着代码敲就能够完成头像的显示,那下面就给大家粗浅的讲讲所涉及到的逻辑关系。
扩展消息:就是你每一次发送消息,都会附带在你发送内容上面的额外消息,他会随着你的内容发送出去,每次会多一点点流量,但微乎其微,个人认为并无多大影响。
显示头像逻辑:区分为本地化缓存和运行内存缓存,在demoHelper中可以发现,有一个成员变量private Map<String, EaseUser> contactList; 这个就是用来保存在运行内存缓存的,只有通过运行缓存,显示头像是最顺畅的,如果每次都从数据库中读取的话,聊天界面会比较卡,有朋友保存在SP里面,以ID做为KEY,头像和昵称等拼接做为value进行缓存,取出后再拆分开分别取值,据说是不卡,大家可以试一下。
         本地化存储是为了在每次打开软件的时候,从本地存储中拿到运行内存中使用做准备,大家可以认真看看demoHelper和MainActivity中的代码。

----------------------------------------------------------------------------------
讲了方法2设置头像,那么方法1,个人不推荐,但这里给出处理的过程,如有个别有需求的,可以按方法1来处理:
1、登录成功后,在手机子线程,访问你们的后台服务器,拿到所有好友的环信ID,头像,昵称。然后按上面的保存方法,保存到本地中,完成后发送广播或EventBus之类到,刷新消息界面和ChatFragment。
2、在getUserInfo中,写和上面扩展消息一样的内容,将如果运行缓存和本地都拿不到,则发起网络请求到后台获取头像,等请求到内容后,再发出广播或EventBus通知刷新消息界面和ChatFragment。

-------------------------------------------------------------------------------------
以上仅为本人在开发过程中的一点小小心得,demo中的保存运存和本地储存的方法,大家也可以单独写,并不会影响程序的运行,当然也有兄弟写过发表,大概根据实际情况择优选取即可。小弟学识浅薄,如果有错漏的,欢迎大家纠正。
如有需要,可以到494167135群中与大家交流学习。本人:乐奇奇,QQ:730326762。大家优先加群,谢谢。
  查看全部
        最近,经常有朋友问到,如何集成环信头像,怎么才能快速显示头像,因时间紧急,很多朋友都没有时间慢慢的研究代码,这里大家稍微花10分钟看一下文章,看完后再花5分钟改一下代码,即可达到你们所要的效果。
        当然这个是在你直接复制了demo中的工具类和必要的UI的前提下实现的。简短说明简单暴力的方法:除UI外的其他所有类先复制到自己工程中,UI部分MainActivity中的代码需要一个一个复制过去,如与自己项目冲突的需要调整,然后ChatActivity/ChatFragment也复制过去,这就可以进行聊天了。不过头像就是大家所遇到的头像显示不了,昵称显示为环信号码。
        环信官方是有给出头像的设置的,不过大部分朋友看了之后都是晕呼呼的。官方给出的提示如下:方法一 从APP服务器获取昵称和头像

昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求

昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二 从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像URI与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。


---------------------------------------------------------------------------------------------
        个人推荐使用方法2,优势比较明显,不仅可以设置头像、昵称,甚至以后出现的是否管理员,或者自己APP中的身份标志,如:店小二、医生、客服等等都可以再定义注明,暴力而简单,不需要考虑对方更新头像或昵称,而软件没重启的情况下怎么去更新头像和昵称等等复杂的问题。本指导以最简单的集成为指导,工具类可使用自己软件中的,或通过别的方式实现。
        方法2的集成步骤:
1、在登录的时候,把自己登录成功时后台返回的信息保存到sharedpreferences中,需要包含需要的头像和昵称。
new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().login(username, password, new EMCallBack() {
@Override
public void onSuccess() {
// 登陆成功,保存用户昵称与头像URL
AppSPUtils.setValueToPrefrences("name", loginBean.getName());
AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl());

// 将自己服务器返回的环信账号、昵称和头像URL设置到帮助类中。
DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName());
DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl());
DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 环信Id

// ------以下参考demo中的,加载群组和加载消息。然后跳转到首页-------
2、AppSPUtils是个人写的一个工具类,大家可以自己写一个,给出参考代码。
public class AppSPUtils {

private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS;

public static SharedPreferences getSharedPreferences(String name) {
return MainApplication.getContext().getSharedPreferences(name,
Context.MODE_PRIVATE | MODE_SPEC);
}

public static SharedPreferences getAppSharedPreferences() {
return getSharedPreferences(Constants.SP_APP);
}

public static String getValueFromPrefrences(String key, String defaultValue) {
return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue);
}

public static void setValueToPrefrences(String key, String value) {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != preferences) {
preferences.edit().putString(key, value).commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 退出登录时要调用
public static void clean() {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != getAppSharedPreferences()) {
getAppSharedPreferences().edit().clear().commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、保存好自己的信息后,已经成功了四分之一,现在是如何将自己的头像昵称等信息发送出去,最简单的就是使用扩展消息了,在ChatActivity中可以看到,基本上只做了一件事,保证只有一个ChatActivity,那我们的代码在哪里?就在ChatFragment里面。找到代码,可以看到其实它是继承自EaseChatFragment,很多内容在easeui中已经做好了。
这时你会发现ChatFragment类中有一个扩展属性的说明,没错,就是这个方法,把你要发送的内容尽情的发送吧,现附上发送头像和昵称的代码:
@Override
public void onSetMessageAttributes(EMMessage message) {
if (isRobot) {
// 设置消息扩展属性
message.setAttribute("em_robot_message", isRobot);
}

// 通过扩展属性,将userPic和userName发送出去。
String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute("userPic", userPic);
}
String userName = AppSPUtils.getValueFromPrefrences("name", "");
if (!TextUtils.isEmpty(userName)) {
message.setAttribute("userName", userName);
}
}
4、发送完成,你已经完成了四分之二的任务了。发送完成后,肯定需要一个接收,其实demo中的广播已经接收好了,那么我们跟随着广播的脚步,来到DemoHelper这个类,初次看这个类,都是云一样的感觉,经过一番查找,发现有个onMessageReceived的方法,并且还有注释“全局监听”,赶紧开工,试试接收吧,可以自己打一下log出来看是不是拿到了我们要的。并且照着demoHelper中的保存方法,将接收到的内容保存起来。
@Override
public void onMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
message.setMsgTime(System.currentTimeMillis());
//************接收并处理扩展消息***********************
String userName = message.getStringAttribute("userName", "");
String userPic = message.getStringAttribute("userPic", "");
String hxIdFrom = message.getFrom();
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(userName);

// 存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
// 存入db
UserDao dao = new UserDao(MainApplication.getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.add(easeUser);
dao.saveContactList(users);

getModel().setContactSynced(true);

// 通知listeners联系人同步完毕
notifyContactsSyncListener(true);
if (isGroupsSyncedWithServer()) {
notifyForRecevingEvents();
}

// ******************扩展信息处理完成**********************
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
// 应用在后台,不需要刷新UI,通知栏提示新消息
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}
5、信息都收到了,就差最后一步就可以显示了,不知道你们是不是激动,反正我是激动了。那在哪里进行显示呢?还是在DemoHelper中,找到getUserInfo方法,代码如下:
private EaseUser getUserInfo(String hxId) {
// 获取user信息,demo是从内存的好友列表里获取,
// 实际开发中,可能还需要从服务器获取用户信息,
// 从服务器获取的数据,最好缓存起来,避免频繁的网络请求

if (hxId.equals(EMClient.getInstance().getCurrentUser())) {
EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo();
return currentUserInfo;
}
EaseUser easeUser;
if (contactList != null && contactList.containsKey(hxId)) {

} else { // 如果内存中没有,则将本地数据库中的取出到内存中。
getContactList();
}
// // TODO 获取不在好友列表里的群成员具体信息,即陌生人信息,demo未实现
// if (user == null && getRobotList() != null) {
// user = getRobotList().get(hxId);
// }
easeUser = contactList.get(hxId);
if(easeUser == null){
easeUser = new EaseUser(hxId);
} else {
if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字为空,则显示环信号码
easeUser.setNick(easeUser.getUsername());
}
}
return easeUser;
}
OK,大功告成,到这里你的头像已经可以显示了。。恭喜你!
有朋友还有疑问,为什么头像是方形的,要变成圆形怎么办?指个路,在easeui中的utils包下,找到EaseUserUtils,这里就是显示用户头像和用户昵称的地方,通过Glide可以轻松显示圆形头像,百度有很多方法,这里就不多讲了,同样,你也可以通过其他图形加载框架来完成。
很多朋友不明白扩展消息的是什么东西,也不明白为什么照着代码敲就能够完成头像的显示,那下面就给大家粗浅的讲讲所涉及到的逻辑关系。
扩展消息:就是你每一次发送消息,都会附带在你发送内容上面的额外消息,他会随着你的内容发送出去,每次会多一点点流量,但微乎其微,个人认为并无多大影响。
显示头像逻辑:区分为本地化缓存和运行内存缓存,在demoHelper中可以发现,有一个成员变量private Map<String, EaseUser> contactList; 这个就是用来保存在运行内存缓存的,只有通过运行缓存,显示头像是最顺畅的,如果每次都从数据库中读取的话,聊天界面会比较卡,有朋友保存在SP里面,以ID做为KEY,头像和昵称等拼接做为value进行缓存,取出后再拆分开分别取值,据说是不卡,大家可以试一下。
         本地化存储是为了在每次打开软件的时候,从本地存储中拿到运行内存中使用做准备,大家可以认真看看demoHelper和MainActivity中的代码。

----------------------------------------------------------------------------------
讲了方法2设置头像,那么方法1,个人不推荐,但这里给出处理的过程,如有个别有需求的,可以按方法1来处理:
1、登录成功后,在手机子线程,访问你们的后台服务器,拿到所有好友的环信ID,头像,昵称。然后按上面的保存方法,保存到本地中,完成后发送广播或EventBus之类到,刷新消息界面和ChatFragment。
2、在getUserInfo中,写和上面扩展消息一样的内容,将如果运行缓存和本地都拿不到,则发起网络请求到后台获取头像,等请求到内容后,再发出广播或EventBus通知刷新消息界面和ChatFragment。

-------------------------------------------------------------------------------------
以上仅为本人在开发过程中的一点小小心得,demo中的保存运存和本地储存的方法,大家也可以单独写,并不会影响程序的运行,当然也有兄弟写过发表,大概根据实际情况择优选取即可。小弟学识浅薄,如果有错漏的,欢迎大家纠正。
如有需要,可以到494167135群中与大家交流学习。本人:乐奇奇,QQ:730326762。大家优先加群,谢谢。
 
33
评论

android中如何显示开发者服务器上的昵称和头像 头像 设置头像 头像和昵称的显示 昵称 头像自定义

江南孤鹜 发表了文章 • 19970 次浏览 • 2016-05-25 15:19 • 来自相关话题

本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757
无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际应用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:





那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490 ... kname
 
引用一下关键文字:方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。
昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
 
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);
 
关键代码:/***************** 环信用户缓存信息 *******************************/
public static final String ChatUserId = "ChatUserId";// 用户的环信ID
public static final String ChatUserPic = "ChatUserPic";
public static final String ChatUserNick = "ChatUserNick";
/***************** 环信用户缓存信息***********end ********************/



UserInfoCacheSvc.java是环信用户信息缓存管理类/**
* 缓存用户信息(主要用于聊天显示昵称和头像)
*/
public class UserInfoCacheSvc {
public static List<UserApiModel> getAllList(){
Dao<UserApiModel, Integer> daoScene = SqliteHelper.getInstance().getUserDao();
try {
List<UserApiModel> list = daoScene.queryBuilder().query();
return list;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getByChatUserName(String chatUserName){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("EaseMobUserName", chatUserName).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static boolean createOrUpdate(String chatUserName, String userNickName, String avatarUrl){
try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getByChatUserName(chatUserName);

int changedLines = 0;
if (user == null){
user = new UserApiModel();
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.create(user);
}else {
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.update(user);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

public static boolean createOrUpdate(UserApiModel model){

if(model == null) return false;

try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getById(model.Id);

if (!StringUtils.isNullOrEmpty(model.getHeadImg())){
String fullPath = "http://image.baidu.com" + model.getHeadImg();
//特别注意:这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

model.setHeadImg(fullPath);
}
int changedLines = 0;
if (user == null){
changedLines = dao.create(model);
}else {
model.setRecordId(user.getRecordId());
changedLines = dao.update(model);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

}首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:public class UserApiModel implements Serializable {

@DatabaseField(generatedId=true)
private int RecordId;

@DatabaseField

public long Id;

@DatabaseField
public String Username;

@DatabaseField
public String Email;

@DatabaseField
public String HeadImg;

@DatabaseField
public String EaseMobUserName;

@DatabaseField
public String EaseMobPassword;
} private static void SaveUserInfo(UserApiModel userInfo){

if(userInfo == null) return;

// 缓存用户信息
PrefUtils.setUserId(userInfo.Id);
PrefUtils.setUserEmail(userInfo.Email);
PrefUtils.setUserName(userInfo.Username);
PrefUtils.setUserPic(userInfo.HeadImg);
PrefUtils.setUserChatId(userInfo.EaseMobUserName);
PrefUtils.setUserChatPwd(userInfo.EaseMobPassword);

UserInfoCacheSvc.createOrUpdate(userInfo);
}然后在接收环信消息的回调函数里保存用户信息,ActyMain.java是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:private EMMessageListener mMessageListener = new EMMessageListener() {

@Override
public void onMessageReceived(List<EMMessage> messages) {
// 提示新消息
for (EMMessage message : messages) {

// 先将头像和昵称保存在本地缓存
try {
String chatUserId = message.getStringAttribute(SharePrefConstant.ChatUserId);
String avatarUrl = message.getStringAttribute(SharePrefConstant.ChatUserPic);
String nickName = message.getStringAttribute(SharePrefConstant.ChatUserNick);

UserInfoCacheSvc.createOrUpdate(chatUserId, nickName, avatarUrl);

} catch (HyphenateException e) {
e.printStackTrace();
}

ChatHelper.getInstance().getNotifier().onNewMsg(message);
}
refreshUIWithMessage();
}

// 此处省略N行代码....
};在安卓项目里,环信页面显示昵称和头像时,都会统一从DemoHelper的getUserInfo函数里获取信息,所以我们要在这里从缓存取用户头像和昵称:private EaseUser getUserInfo(String username){
//获取user信息,demo是从内存的好友列表里获取,
//实际开发中,可能还需要从服务器获取用户信息,
//从服务器获取的数据,最好缓存起来,避免频繁的网络请求
EaseUser user = null;
// 从缓存里取昵称和头像
UserApiModel userInfo = UserInfoCacheSvc.getByChatUserName(username);
if (userInfo != null){
user = new EaseUser(username);
user.setAvatar(userInfo.getHeadImg());
user.setNick(userInfo.getUsername());
}

return user;
}最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在
ChatFragment.java里: @Override
public void onSetMessageAttributes(EMMessage message) {
setUserInfoAttribute(message);
}

/**
* 设置用户的属性,
* 通过消息的扩展,传递客服系统用户的属性信息
* @param message
*/
private void setUserInfoAttribute(EMMessage message) {
try {
message.setAttribute(SharePrefConstant.ChatUserId, PrefUtils.getUserChatId());
message.setAttribute(SharePrefConstant.ChatUserNick, PrefUtils.getUserName());
message.setAttribute(SharePrefConstant.ChatUserPic, "http://image.baidu.com" + PrefUtils.getUserPic()) ;//这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

} catch (Exception e) {
e.printStackTrace();
}
}有不当之处,欢迎指正~~~谢谢
部分源码因为是公司项目代码,所以没有在文章里提供(而且代码量太多,也不便于阅读)。需要源码的童鞋,可以联系我。等我有空,我整理一下公司项目,然后再share开源给大家。
相关类文件下载:

EaseUI头像和昵称相关类文件_0701.zip


 
本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757
如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063,
或者加本人QQ:364223587,加Q请认准以下正宗小马头像: 查看全部

本文方法已经废弃!请看作者另外一篇文章:


在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757


无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际应用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:
444.png


那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490 ... kname
 
引用一下关键文字:
方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。
昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
 
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);
 
关键代码:
/***************** 环信用户缓存信息 *******************************/
public static final String ChatUserId = "ChatUserId";// 用户的环信ID
public static final String ChatUserPic = "ChatUserPic";
public static final String ChatUserNick = "ChatUserNick";
/***************** 环信用户缓存信息***********end ********************/



UserInfoCacheSvc.java是环信用户信息缓存管理类
/**
* 缓存用户信息(主要用于聊天显示昵称和头像)
*/
public class UserInfoCacheSvc {
public static List<UserApiModel> getAllList(){
Dao<UserApiModel, Integer> daoScene = SqliteHelper.getInstance().getUserDao();
try {
List<UserApiModel> list = daoScene.queryBuilder().query();
return list;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getByChatUserName(String chatUserName){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("EaseMobUserName", chatUserName).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static boolean createOrUpdate(String chatUserName, String userNickName, String avatarUrl){
try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getByChatUserName(chatUserName);

int changedLines = 0;
if (user == null){
user = new UserApiModel();
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.create(user);
}else {
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.update(user);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

public static boolean createOrUpdate(UserApiModel model){

if(model == null) return false;

try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getById(model.Id);

if (!StringUtils.isNullOrEmpty(model.getHeadImg())){
String fullPath = "http://image.baidu.com" + model.getHeadImg();
//特别注意:这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

model.setHeadImg(fullPath);
}
int changedLines = 0;
if (user == null){
changedLines = dao.create(model);
}else {
model.setRecordId(user.getRecordId());
changedLines = dao.update(model);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

}
首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:
public class UserApiModel implements Serializable {

@DatabaseField(generatedId=true)
private int RecordId;

@DatabaseField

public long Id;

@DatabaseField
public String Username;

@DatabaseField
public String Email;

@DatabaseField
public String HeadImg;

@DatabaseField
public String EaseMobUserName;

@DatabaseField
public String EaseMobPassword;
}
 
private static void SaveUserInfo(UserApiModel userInfo){

if(userInfo == null) return;

// 缓存用户信息
PrefUtils.setUserId(userInfo.Id);
PrefUtils.setUserEmail(userInfo.Email);
PrefUtils.setUserName(userInfo.Username);
PrefUtils.setUserPic(userInfo.HeadImg);
PrefUtils.setUserChatId(userInfo.EaseMobUserName);
PrefUtils.setUserChatPwd(userInfo.EaseMobPassword);

UserInfoCacheSvc.createOrUpdate(userInfo);
}
然后在接收环信消息的回调函数里保存用户信息,ActyMain.java是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:
private EMMessageListener mMessageListener = new EMMessageListener() {

@Override
public void onMessageReceived(List<EMMessage> messages) {
// 提示新消息
for (EMMessage message : messages) {

// 先将头像和昵称保存在本地缓存
try {
String chatUserId = message.getStringAttribute(SharePrefConstant.ChatUserId);
String avatarUrl = message.getStringAttribute(SharePrefConstant.ChatUserPic);
String nickName = message.getStringAttribute(SharePrefConstant.ChatUserNick);

UserInfoCacheSvc.createOrUpdate(chatUserId, nickName, avatarUrl);

} catch (HyphenateException e) {
e.printStackTrace();
}

ChatHelper.getInstance().getNotifier().onNewMsg(message);
}
refreshUIWithMessage();
}

// 此处省略N行代码....
};
在安卓项目里,环信页面显示昵称和头像时,都会统一从DemoHelper的getUserInfo函数里获取信息,所以我们要在这里从缓存取用户头像和昵称:
private EaseUser getUserInfo(String username){
//获取user信息,demo是从内存的好友列表里获取,
//实际开发中,可能还需要从服务器获取用户信息,
//从服务器获取的数据,最好缓存起来,避免频繁的网络请求
EaseUser user = null;
// 从缓存里取昵称和头像
UserApiModel userInfo = UserInfoCacheSvc.getByChatUserName(username);
if (userInfo != null){
user = new EaseUser(username);
user.setAvatar(userInfo.getHeadImg());
user.setNick(userInfo.getUsername());
}

return user;
}
最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在
ChatFragment.java里:
    @Override
public void onSetMessageAttributes(EMMessage message) {
setUserInfoAttribute(message);
}

/**
* 设置用户的属性,
* 通过消息的扩展,传递客服系统用户的属性信息
* @param message
*/
private void setUserInfoAttribute(EMMessage message) {
try {
message.setAttribute(SharePrefConstant.ChatUserId, PrefUtils.getUserChatId());
message.setAttribute(SharePrefConstant.ChatUserNick, PrefUtils.getUserName());
message.setAttribute(SharePrefConstant.ChatUserPic, "http://image.baidu.com" + PrefUtils.getUserPic()) ;//这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

} catch (Exception e) {
e.printStackTrace();
}
}
有不当之处,欢迎指正~~~谢谢
部分源码因为是公司项目代码,所以没有在文章里提供(而且代码量太多,也不便于阅读)。需要源码的童鞋,可以联系我。等我有空,我整理一下公司项目,然后再share开源给大家。
相关类文件下载:

 
本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063,
或者加本人QQ:364223587,加Q请认准以下正宗小马头像:


10
评论

IOS中如何显示开发者服务器上的昵称和头像 头像 头像自定义 头像和昵称 设置头像 头像 昵称 扩展

江南孤鹜 发表了文章 • 45981 次浏览 • 2016-05-25 14:49 • 来自相关话题

无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际运用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:




 
那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490integrationcases/10nickname
 
引用一下关键文字:
方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);

 
IOS关键代码:// 环信聊天用的昵称和头像(发送聊天消息时,要附带这3个属性)
#define kChatUserId @"ChatUserId"// 环信账号
#define kChatUserNick @"ChatUserNick"
#define kChatUserPic @"ChatUserPic"
 ChatUserCacheInfo是环信用户信息缓存管理类
ChatUserCacheInfo.h#import <Foundation/Foundation.h>

@interface ChatUserCacheInfo : NSObject
@property(nonatomic,copy)NSString* Id;
@property(nonatomic,copy)NSString* NickName;
@property(nonatomic,copy)NSString* AvatarUrl;
@end


@interface ChatUserCacheUtil : NSObject

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName;

+(void)saveDict:(NSDictionary *)userinfo;

+(void)saveModel:(UserApiModel*)user;

+(ChatUserCacheInfo*)queryById:(NSString *)userid;

@end









ChatUserCacheUtil.m#import "ChatUserCacheUtil.h"
#import "FMDB.h"

#define DBNAME @"cache_data.db"

@implementation ChatUserCacheInfo

@end

@implementation ChatUserCacheUtil

+(void)createTable:(FMDatabase *)db
{
if ([db open]) {
if (![db tableExists :@"userinfo"]) {
if ([db executeUpdate:@"create table userinfo (userid text, username text, userimage text)"]) {
NSLog(@"create table success");
}else{
NSLog(@"fail to create table");
}
}else {
NSLog(@"table is already exist");
}
}else{
NSLog(@"fail to open");
}
}

+ (void)clearTableData:(FMDatabase *)db
{
if ([db executeUpdate:@"DELETE FROM userinfo"]) {
NSLog(@"clear successed");
}else{
NSLog(@"fail to clear");
}
}

+(FMDatabase*)getDB{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:DBNAME];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
[self createTable:db];
return db;
}

+(void)saveModel:(UserApiModel*)user{
[ChatUserCacheUtil saveInfo:user.EaseMobUserName imgId:user.HeadImg nickName:user.Username];
}

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName{
NSMutableDictionary *extDic = [NSMutableDictionary dictionary];
[extDic setValue:openId forKey:kChatUserId];
[extDic setValue:@"[url=http://img.baidu.com"]http://img.baidu.com/"[/url]+imgId forKey:kChatUserPic];//完整图片路径"http://img.baidu.com/1234"。如果imgId是相对路径,那完整路径就是类似"http://img.baidu.com/abc.jpg"
[extDic setValue:nickName forKey:kChatUserNick];
[ChatUserCacheUtil saveDict:extDic];
}

+(void)saveDict:(NSDictionary *)userinfo{
FMDatabase *db = [self getDB];

NSString *userid = [userinfo objectForKey:kChatUserId];
if ([db executeUpdate:@"DELETE FROM userinfo where userid = ?", userid]) {
DLog(@"删除成功");
}else{
DLog(@"删除失败");
}
NSString *username = [userinfo objectForKey:kChatUserNick];
NSString *userimage = [userinfo objectForKey:kChatUserPic];
if ([db executeUpdate:@"INSERT INTO userinfo (userid, username, userimage) VALUES (?, ?, ?)", userid,username,userimage]) {
DLog(@"插入成功");
}else{
DLog(@"插入失败");
}

// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@ %@ %@",userid,username,userimage);
}

rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo"];
while ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询所有 %@ %@ %@",userid,username,userimage);
}
[rs close];
// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
[db close];

}

+(ChatUserCacheInfo*)queryById:(NSString *)userid{
FMDatabase *db = [self getDB];
if ([db open]) {
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {

ChatUserCacheInfo *userInfo = [[ChatUserCacheInfo alloc] init];

userInfo.Id = [rs stringForColumn:@"userid"];
userInfo.NickName = [rs stringForColumn:@"username"];
userInfo.AvatarUrl = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@",userInfo);
return userInfo;
}else{
return nil;
}
}else{
return nil;
}
}


@end首先要在用户登录或注册成功后,返回用户登录信息时,缓存一下用户信息:@protocol UserApiModel <NSObject>

@end

@interface UserApiModel : BaseJSONModel
@property(nonatomic, assign)int Id;
@property(nonatomic, copy)NSString *Username;
@property(nonatomic, copy)NSString *Email;
@property(nonatomic, copy)NSString *HeadImg;
@property(nonatomic, copy)NSString *EaseMobUserName;
@property(nonatomic, copy)NSString *EaseMobPassword;
@end

// 登录成功后返回用户model,需要为环信聊天窗口缓存用户信息
[ChatUserCacheUtil saveModel:user];
然后在接收环信消息的回调函数里保存用户信息,HsMainViewController.m是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:// 收到消息回调
-(void) didReceiveMessage:(EMMessage *)message
{
[ChatUserCacheUtil saveDict:message.ext];

BOOL needShowNotification = (message.messageType != eMessageTypeChat) ? [self needShowNotification:message.conversationChatter] : YES;
if (needShowNotification) {
#if !TARGET_IPHONE_SIMULATOR

BOOL isAppActivity = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
if (!isAppActivity) {
[self showNotificationWithMessage:message];
}else {
[self playSoundAndVibration];
}
#endif
}
}环信页面主要是在ChatViewController和ConversationListViewController里显示用户对话,所以我们要在这两个页面里从缓存取用户头像和昵称,先从ChatViewController开始:- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
id<IMessageModel> model = [[EaseMessageModel alloc] initWithMessage:message];

ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.nickname];
if (userinfo != nil) {
model.nickname = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
model.failImageName = @"imageDownloadFail";

return model;
}然后是ConversationListViewController:#pragma mark - EaseConversationListViewControllerDataSource

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
modelForConversation:(EMConversation *)conversation
{
EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
if (model.conversation.conversationType == eConversationTypeChat) {
ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.conversation.chatter];
if (userinfo != nil) {
model.title = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}
model.avatarImage = PlaceholderImgChatUser;
} else if (model.conversation.conversationType == eConversationTypeGroupChat) {
// 此处省略100行代码........
}
}最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在EaseSDKHelper.m里:// 重新消息扩展组织
+(NSMutableDictionary*)reGetMessageExt:(NSDictionary *)messageExt{
NSMutableDictionary *extDic = [NSMutableDictionary dictionaryWithDictionary:messageExt];
[extDic setValue:[SettingData share].UserChatId forKey:kChatUserId];
[extDic setValue:[SettingData share].UserHeadImg.ServerThumbUrlStr forKey:kChatUserPic];
[extDic setValue:[SettingData share].UserName forKey:kChatUserNick];
return extDic;
}

+ (EMMessage *)sendTextMessage:(NSString *)text
to:(NSString *)toUser
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt

{
// 表情映射。
NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:text];
EMChatText *textChat = [[EMChatText alloc] initWithText:willSendText];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:textChat];
EMMessage *message = [[EMMessage alloc] initWithReceiver:toUser bodies:[NSArray arrayWithObject:body]];
message.requireEncryption = requireEncryption;
message.messageType = messageType;

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:nil];

return retMessage;
}


+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
return [self sendImageMessageWithImage:image to:to messageType:messageType requireEncryption:requireEncryption messageExt:messageExt quality:0.6 progress:progress];
}

+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
quality:(float)quality
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略9行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVoiceMessageWithLocalPath:(NSString *)localPath
duration:(NSInteger)duration
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVideoMessageWithURL:(NSURL *)url
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendFileMessage:(EMChatFile *)chatFile
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}
有不当之处,欢迎指正~~谢谢。QQ:364223587
 
以上代码为SDK V2版本,如果集成的是V3版本,请移步源码:
http://git.oschina.net/markies/ChatDemo-UI3.00-Simple
思路其实跟V2差不多,最大区别V3的回调方法didReceiveMessages比V2多了个【s】。

ChatUserCacheUtil我已经重命名为:UserCacheManager
 

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063
  查看全部
无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际运用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:
1.png

 
那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490integrationcases/10nickname
 
引用一下关键文字:

方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。


 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);

 
IOS关键代码:
// 环信聊天用的昵称和头像(发送聊天消息时,要附带这3个属性)
#define kChatUserId @"ChatUserId"// 环信账号
#define kChatUserNick @"ChatUserNick"
#define kChatUserPic @"ChatUserPic"

 ChatUserCacheInfo是环信用户信息缓存管理类
ChatUserCacheInfo.h
#import <Foundation/Foundation.h>

@interface ChatUserCacheInfo : NSObject
@property(nonatomic,copy)NSString* Id;
@property(nonatomic,copy)NSString* NickName;
@property(nonatomic,copy)NSString* AvatarUrl;
@end


@interface ChatUserCacheUtil : NSObject

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName;

+(void)saveDict:(NSDictionary *)userinfo;

+(void)saveModel:(UserApiModel*)user;

+(ChatUserCacheInfo*)queryById:(NSString *)userid;

@end









ChatUserCacheUtil.m
#import "ChatUserCacheUtil.h"
#import "FMDB.h"

#define DBNAME @"cache_data.db"

@implementation ChatUserCacheInfo

@end

@implementation ChatUserCacheUtil

+(void)createTable:(FMDatabase *)db
{
if ([db open]) {
if (![db tableExists :@"userinfo"]) {
if ([db executeUpdate:@"create table userinfo (userid text, username text, userimage text)"]) {
NSLog(@"create table success");
}else{
NSLog(@"fail to create table");
}
}else {
NSLog(@"table is already exist");
}
}else{
NSLog(@"fail to open");
}
}

+ (void)clearTableData:(FMDatabase *)db
{
if ([db executeUpdate:@"DELETE FROM userinfo"]) {
NSLog(@"clear successed");
}else{
NSLog(@"fail to clear");
}
}

+(FMDatabase*)getDB{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:DBNAME];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
[self createTable:db];
return db;
}

+(void)saveModel:(UserApiModel*)user{
[ChatUserCacheUtil saveInfo:user.EaseMobUserName imgId:user.HeadImg nickName:user.Username];
}

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName{
NSMutableDictionary *extDic = [NSMutableDictionary dictionary];
[extDic setValue:openId forKey:kChatUserId];
[extDic setValue:@"[url=http://img.baidu.com"]http://img.baidu.com/"[/url]+imgId forKey:kChatUserPic];//完整图片路径"http://img.baidu.com/1234"。如果imgId是相对路径,那完整路径就是类似"http://img.baidu.com/abc.jpg"
[extDic setValue:nickName forKey:kChatUserNick];
[ChatUserCacheUtil saveDict:extDic];
}

+(void)saveDict:(NSDictionary *)userinfo{
FMDatabase *db = [self getDB];

NSString *userid = [userinfo objectForKey:kChatUserId];
if ([db executeUpdate:@"DELETE FROM userinfo where userid = ?", userid]) {
DLog(@"删除成功");
}else{
DLog(@"删除失败");
}
NSString *username = [userinfo objectForKey:kChatUserNick];
NSString *userimage = [userinfo objectForKey:kChatUserPic];
if ([db executeUpdate:@"INSERT INTO userinfo (userid, username, userimage) VALUES (?, ?, ?)", userid,username,userimage]) {
DLog(@"插入成功");
}else{
DLog(@"插入失败");
}

// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@ %@ %@",userid,username,userimage);
}

rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo"];
while ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询所有 %@ %@ %@",userid,username,userimage);
}
[rs close];
// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
[db close];

}

+(ChatUserCacheInfo*)queryById:(NSString *)userid{
FMDatabase *db = [self getDB];
if ([db open]) {
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {

ChatUserCacheInfo *userInfo = [[ChatUserCacheInfo alloc] init];

userInfo.Id = [rs stringForColumn:@"userid"];
userInfo.NickName = [rs stringForColumn:@"username"];
userInfo.AvatarUrl = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@",userInfo);
return userInfo;
}else{
return nil;
}
}else{
return nil;
}
}


@end
首先要在用户登录或注册成功后,返回用户登录信息时,缓存一下用户信息:
@protocol UserApiModel <NSObject>

@end

@interface UserApiModel : BaseJSONModel
@property(nonatomic, assign)int Id;
@property(nonatomic, copy)NSString *Username;
@property(nonatomic, copy)NSString *Email;
@property(nonatomic, copy)NSString *HeadImg;
@property(nonatomic, copy)NSString *EaseMobUserName;
@property(nonatomic, copy)NSString *EaseMobPassword;
@end

// 登录成功后返回用户model,需要为环信聊天窗口缓存用户信息
[ChatUserCacheUtil saveModel:user];

然后在接收环信消息的回调函数里保存用户信息,HsMainViewController.m是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:
// 收到消息回调
-(void) didReceiveMessage:(EMMessage *)message
{
[ChatUserCacheUtil saveDict:message.ext];

BOOL needShowNotification = (message.messageType != eMessageTypeChat) ? [self needShowNotification:message.conversationChatter] : YES;
if (needShowNotification) {
#if !TARGET_IPHONE_SIMULATOR

BOOL isAppActivity = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
if (!isAppActivity) {
[self showNotificationWithMessage:message];
}else {
[self playSoundAndVibration];
}
#endif
}
}
环信页面主要是在ChatViewController和ConversationListViewController里显示用户对话,所以我们要在这两个页面里从缓存取用户头像和昵称,先从ChatViewController开始:
- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
id<IMessageModel> model = [[EaseMessageModel alloc] initWithMessage:message];

ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.nickname];
if (userinfo != nil) {
model.nickname = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
model.failImageName = @"imageDownloadFail";

return model;
}
然后是ConversationListViewController:
#pragma mark - EaseConversationListViewControllerDataSource

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
modelForConversation:(EMConversation *)conversation
{
EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
if (model.conversation.conversationType == eConversationTypeChat) {
ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.conversation.chatter];
if (userinfo != nil) {
model.title = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}
model.avatarImage = PlaceholderImgChatUser;
} else if (model.conversation.conversationType == eConversationTypeGroupChat) {
// 此处省略100行代码........
}
}
最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在EaseSDKHelper.m里:
// 重新消息扩展组织
+(NSMutableDictionary*)reGetMessageExt:(NSDictionary *)messageExt{
NSMutableDictionary *extDic = [NSMutableDictionary dictionaryWithDictionary:messageExt];
[extDic setValue:[SettingData share].UserChatId forKey:kChatUserId];
[extDic setValue:[SettingData share].UserHeadImg.ServerThumbUrlStr forKey:kChatUserPic];
[extDic setValue:[SettingData share].UserName forKey:kChatUserNick];
return extDic;
}

+ (EMMessage *)sendTextMessage:(NSString *)text
to:(NSString *)toUser
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt

{
// 表情映射。
NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:text];
EMChatText *textChat = [[EMChatText alloc] initWithText:willSendText];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:textChat];
EMMessage *message = [[EMMessage alloc] initWithReceiver:toUser bodies:[NSArray arrayWithObject:body]];
message.requireEncryption = requireEncryption;
message.messageType = messageType;

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:nil];

return retMessage;
}


+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
return [self sendImageMessageWithImage:image to:to messageType:messageType requireEncryption:requireEncryption messageExt:messageExt quality:0.6 progress:progress];
}

+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
quality:(float)quality
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略9行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVoiceMessageWithLocalPath:(NSString *)localPath
duration:(NSInteger)duration
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVideoMessageWithURL:(NSURL *)url
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendFileMessage:(EMChatFile *)chatFile
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

有不当之处,欢迎指正~~谢谢。QQ:364223587
 
以上代码为SDK V2版本,如果集成的是V3版本,请移步源码:
http://git.oschina.net/markies/ChatDemo-UI3.00-Simple
思路其实跟V2差不多,最大区别V3的回调方法didReceiveMessages比V2多了个【s】。

ChatUserCacheUtil我已经重命名为:UserCacheManager
 

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063
 
4
评论

【开源项目】全国首个开源直播小程序源码 环信公开课 小程序 直播

beyond 发表了文章 • 9361 次浏览 • 2018-07-20 17:30 • 来自相关话题

今天你看直播了吗?拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 





作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载


小程序直播demo_2018-06-21.zip







直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 




2、导入源码:将附件的源码解压直接导入 







环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]




填写对相关信息进行注册





注册成功后进行登录




注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用




输入应用名称等信息
 





创建成功后点击应用进入





需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量




3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Tokencurl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'返回格式{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址curl -X POST -H "Authorization: Bearer [管理员Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"成功返回格式:{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户





点击注册IM用户





填写用户信息





创建用户的过程同样也可以通过REST API形式进行curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'
注:应用必须为开放注册





将注册的用户添加为主播curl -X POST -H "Authorization: [管理员Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'返回结果示例:{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播





点击新建房间





填写房间信息




创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件





修改appkey为自己应用的appkey





打开pages/live/index.js修改房间默认拉流地址及直播间房间号





四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:curl -X GET -H "Authorization: Bearer [用户Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]
响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。 查看全部
今天你看直播了吗?
拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 
微信图片_20180725162426.jpg


作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载



预览图.jpg

直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 
Catch9A07(07-20-17-38-30).jpg

2、导入源码:将附件的源码解压直接导入 


Catch1C69(07-20-17-38-30).jpg


环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]
1.png

填写对相关信息进行注册

2.png

注册成功后进行登录
3.png

注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用
4.png

输入应用名称等信息
 

5.png

创建成功后点击应用进入

6.png

需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量
7.png

3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Token
curl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'
返回格式
{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址
curl -X POST -H "Authorization: Bearer [管理员Token]"  " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"
成功返回格式:
{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户

8.png

点击注册IM用户

9.png

填写用户信息

10.png

创建用户的过程同样也可以通过REST API形式进行
curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'

注:应用必须为开放注册

11.png

将注册的用户添加为主播
curl -X POST -H "Authorization: [管理员Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'
返回结果示例:
{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播

12.png

点击新建房间

13.png

填写房间信息
14.png

创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件

15.png

修改appkey为自己应用的appkey

16.png

打开pages/live/index.js修改房间默认拉流地址及直播间房间号

17.png

四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:
curl -X GET -H "Authorization: Bearer  [用户Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]

响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:
curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"
响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。
19
评论

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

dujiepeng 发表了文章 • 19673 次浏览 • 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...小伙伴们还有什么想知道欢迎跟帖提出。
 
12
回复

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

xiaoyan2015 回复了问题 • 13 人关注 • 13141 次浏览 • 2019-01-14 10:04 • 来自相关话题

12
回复

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

回复

xiaoyan2015 回复了问题 • 13 人关注 • 13141 次浏览 • 2019-01-14 10:04 • 来自相关话题

4
评论

【开源项目】全国首个开源直播小程序源码 环信公开课 小程序 直播

beyond 发表了文章 • 9361 次浏览 • 2018-07-20 17:30 • 来自相关话题

今天你看直播了吗?拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 





作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载


小程序直播demo_2018-06-21.zip







直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 




2、导入源码:将附件的源码解压直接导入 







环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]




填写对相关信息进行注册





注册成功后进行登录




注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用




输入应用名称等信息
 





创建成功后点击应用进入





需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量




3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Tokencurl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'返回格式{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址curl -X POST -H "Authorization: Bearer [管理员Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"成功返回格式:{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户





点击注册IM用户





填写用户信息





创建用户的过程同样也可以通过REST API形式进行curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'
注:应用必须为开放注册





将注册的用户添加为主播curl -X POST -H "Authorization: [管理员Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'返回结果示例:{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播





点击新建房间





填写房间信息




创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件





修改appkey为自己应用的appkey





打开pages/live/index.js修改房间默认拉流地址及直播间房间号





四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:curl -X GET -H "Authorization: Bearer [用户Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]
响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。 查看全部
今天你看直播了吗?
拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 
微信图片_20180725162426.jpg


作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载



预览图.jpg

直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 
Catch9A07(07-20-17-38-30).jpg

2、导入源码:将附件的源码解压直接导入 


Catch1C69(07-20-17-38-30).jpg


环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]
1.png

填写对相关信息进行注册

2.png

注册成功后进行登录
3.png

注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用
4.png

输入应用名称等信息
 

5.png

创建成功后点击应用进入

6.png

需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量
7.png

3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Token
curl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'
返回格式
{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址
curl -X POST -H "Authorization: Bearer [管理员Token]"  " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"
成功返回格式:
{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户

8.png

点击注册IM用户

9.png

填写用户信息

10.png

创建用户的过程同样也可以通过REST API形式进行
curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'

注:应用必须为开放注册

11.png

将注册的用户添加为主播
curl -X POST -H "Authorization: [管理员Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'
返回结果示例:
{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播

12.png

点击新建房间

13.png

填写房间信息
14.png

创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件

15.png

修改appkey为自己应用的appkey

16.png

打开pages/live/index.js修改房间默认拉流地址及直播间房间号

17.png

四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:
curl -X GET -H "Authorization: Bearer  [用户Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]

响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:
curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"
响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。
19
评论

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

dujiepeng 发表了文章 • 19673 次浏览 • 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...小伙伴们还有什么想知道欢迎跟帖提出。
 
2
回复

android 3.X 设置头像 设置头像

回复

李。 回复了问题 • 2 人关注 • 1114 次浏览 • 2016-10-25 16:08 • 来自相关话题

1
回复

android 3.X 设置聊天里自己的头像 设置头像

回复

Wxin 回复了问题 • 2 人关注 • 1160 次浏览 • 2016-09-26 19:08 • 来自相关话题

12
回复

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

回复

xiaoyan2015 回复了问题 • 13 人关注 • 13141 次浏览 • 2019-01-14 10:04 • 来自相关话题

4
评论

【开源项目】全国首个开源直播小程序源码 环信公开课 小程序 直播

beyond 发表了文章 • 9361 次浏览 • 2018-07-20 17:30 • 来自相关话题

今天你看直播了吗?拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 





作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载


小程序直播demo_2018-06-21.zip







直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 




2、导入源码:将附件的源码解压直接导入 







环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]




填写对相关信息进行注册





注册成功后进行登录




注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用




输入应用名称等信息
 





创建成功后点击应用进入





需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量




3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Tokencurl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'返回格式{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址curl -X POST -H "Authorization: Bearer [管理员Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"成功返回格式:{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户





点击注册IM用户





填写用户信息





创建用户的过程同样也可以通过REST API形式进行curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'
注:应用必须为开放注册





将注册的用户添加为主播curl -X POST -H "Authorization: [管理员Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'返回结果示例:{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播





点击新建房间





填写房间信息




创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件





修改appkey为自己应用的appkey





打开pages/live/index.js修改房间默认拉流地址及直播间房间号





四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:curl -X GET -H "Authorization: Bearer [用户Token]" https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]
响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"响应:{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。 查看全部
今天你看直播了吗?
拥有10亿微信生态用户的小程序已经成为了继移动互联后的又一个现象级风口,随着微信小程序对外开放实时音视频录制及播放等更多连接能力,小程序与直播强强联合,在各行各业找到了非常多的玩法,小程序直播相比微信直播和APP直播更加简洁、流畅、低延时、多入口等众多优势迅速向商业直播领域及泛娱乐直播领域蔓延。从小游戏、内容付费、工具、大数据、社交电商创业者到传统品牌商们,都在努力搭上小程序直播这辆快车,以免错过微信生态里新的流量洼地。
 
微信图片_20180725162426.jpg


作为一名环信生态圈资深开发者,本着对技术的热衷,对环信的眷恋和对党的忠诚,基于环信即时通讯云写了“直播购物小程序”,目前项目源码已全部免费开放,希望对有需求的企业和开发者提供一个思路和参考。
直播购物小程序源码github地址:https://github.com/YuTongNetworkTechnology/wechat_live/tree/master 
git打不开可直接点下面链接下载



预览图.jpg

直播购物小程序运行预览图 
 
小程序体验指南(仅需两步):
 
1、下载微信小程序开发工具,下载地址:https://developers.weixin.qq.c ... .html 
 
Catch9A07(07-20-17-38-30).jpg

2、导入源码:将附件的源码解压直接导入 


Catch1C69(07-20-17-38-30).jpg


环信小程序直播技术文档
一、 使用的技术
1、 环信IM直播室。
2、 微信小程序实时音视频播放组件live-player。
3、 推流软件(obs、易推流)等推流。
4、 视频流服务器(UCLOUD、七牛、腾讯)等视频流服务器。
二、 系统使用流程。
1、 视频推流软件将视频流推到流服务器。
2、 打开视频直播demo小程序注册环信账号。
3、 进入软件直播室进行测试。
三、 技术流程及使用的SDk
1、 注册环信账号
打开https://www.easemob.com/ 环信官网,点击右上角注册按钮,选择[注册即时通讯云]
1.png

填写对相关信息进行注册

2.png

注册成功后进行登录
3.png

注:新注册用户需进行账号的认证。
2、 直播应用创建
登录成功点击应用列表选择创建应用
4.png

输入应用名称等信息
 

5.png

创建成功后点击应用进入

6.png

需要注意的是应用的OrgName 和AppName这两个是以后都需要用到的两个参数变量
7.png

3、 直播创建
1)在创建直播之前需要对应用进行设置首先需要设置应用的直播流地址
第一步获取应用管理员的Token
curl -X POST "https://a1.easemob.com/[应用OrgName]/[应用AppName]/token" -d '{"grant_type":"client_credentials","client_id":"[应用client_id]","client_secret":"[应用] client_secret"}'
返回格式
{
"access_token":"YWMtWY779DgJEeS2h9OR7fw4QgAAAUmO4Qukwd9cfJSpkWHiOa7MCSk0MrkVIco",
"expires_in":5184000,
"application":"c03b3e30-046a-11e4-8ed1-5701cdaaa0e4"












第二步设置直播流地址
curl -X POST -H "Authorization: Bearer [管理员Token]"  " https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms/stream_url -d '{"pc_pull":"[pc拉流地址]","pc_push":"[pc推流地址]","mobile_pull":"[手机拉流地址]","mobile_push":"[手机推流地址]"}'"
成功返回格式:
{
"action": "post",
"application": "e1a09de0-0e03-11e7-ad8e-a1d913615409",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"pc_pull": true,
"mobile_push": true,
"mobile_pull": true,
"pc_push": true
},
"timestamp": 1494084474885,
"duration": 1,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












2)创建主播
点击IM用户

8.png

点击注册IM用户

9.png

填写用户信息

10.png

创建用户的过程同样也可以通过REST API形式进行
curl -X POST -i " https://a1.easemob.com/[应用OrgName]/[应用AppName]/users" -d '{"username":"[用户名]","password":"[密码]"}'

注:应用必须为开放注册

11.png

将注册的用户添加为主播
curl -X POST -H "Authorization: [管理员Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/super_admin -d'{"superadmin":"[IM用户名]"}'
返回结果示例:
{
"action": "post",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"result": "success"
},
"timestamp": 1496236798886,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui"
}












3)创建直播
点击直播

12.png

点击新建房间

13.png

填写房间信息
14.png

创建房间同时也可以使用REST API形式进行详情可以查看http://docs.easemob.com/im/live/server-integration环信官方文档。
4、 小程序demo集成使用
小程序直播购物demo集成官方WebIM SDK详情请查看https://github.com/easemob/webim-weixin-xcx
Demo具体配置如下
打开demo 下sdk配置文件

15.png

修改appkey为自己应用的appkey

16.png

打开pages/live/index.js修改房间默认拉流地址及直播间房间号

17.png

四、 扩展说明
Demo中房间为固定测试房间,实际使用中应获取环信直播的房间信息及房间列表。具体如下:
获取直播间列表:
curl -X GET -H "Authorization: Bearer  [用户Token]"  https://a1.easemob.com/[应用OrgName]/[应用AppName]/liverooms?ongoing=true&limit=[获取数量]&cursor=[游标地址(不填写为充开始查询)]

响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"params": {
"cursor": [
"ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6MzE"
],
"ongoing": [
"true"
],
"limit": [
"2"
]
},
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": [
{
"id": "1924",
"chatroom_id": "17177265635330",
"title": "具体了",
"desc": "就咯",
"startTime": 1495779917352,
"endTime": 1495779917352,
"anchor": "wuls",
"gift_count": 0,
"praise_count": 0,
"current_user_count": 8,
"max_user_count": 9,
"status": "ongoing",
"cover_picture_url": "",
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1924_1"
},
{
"id": "1922",
"chatroom_id": "17175003856897",
"title": "香山",
"desc": "随便",
"startTime": 1495777760957,
"endTime": 1495777760957,
"anchor": "sx001",
"gift_count": 0,
"praise_count": 8,
"current_user_count": 1,
"max_user_count": 3,
"status": "ongoing",
"cover_picture_url": "http://127.0.0.1:8080/easemob- ... ot%3B,
"pc_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"pc_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_pull_url": "rtmp://vlive3.rtmp.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1",
"mobile_push_url": "rtmp://publish3.cdn.ucloud.com.cn/ucloud/easemob-demo_chatdemoui_1922_1"
}
],
"timestamp": 1496303336669,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"cursor": "ZGNiMjRmNGY1YjczYjlhYTNkYjk1MDY2YmEyNzFmODQ6aW06Y2hhdHJvb206ZWFzZW1vYi1kZW1vI2NoYXRkZW1vdWk6NDk",
"count": 2
}












获取直播间详情:
curl -X GET -H "Authorization: Bearer [用户Token]" " https://a1.easemob.com/[应用OrgName]/[应用AppName]/[房间id]/status"
响应:
{
"action": "get",
"application": "4d7e4ba0-dc4a-11e3-90d5-e1ffbaacdaf5",
"uri": "http://127.0.0.1:8080/easemob- ... ot%3B,
"entities": [ ],
"data": {
"liveRoomID": "1946",
"status": "ongoing"
},
"timestamp": 1496234759930,
"duration": 0,
"organization": "easemob-demo",
"applicationName": "chatdemoui",
"count": 0
}














 
使用环信直播购物小程序遇到任何问题欢迎跟帖讨论。
19
评论

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

dujiepeng 发表了文章 • 19673 次浏览 • 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...小伙伴们还有什么想知道欢迎跟帖提出。
 
3
评论

草草们的忧伤:环信IM昵称和头像 头像 昵称 扩展 头像 设置头像

江南孤鹜 发表了文章 • 12318 次浏览 • 2016-11-08 09:35 • 来自相关话题

最近天气转冷了,写篇文章,给大家暖暖心~





 
在环信草草群(群号:340452063)中,无论是安卓还是IOS或者WebIM,每天遇到最多的问题就是“如何显示昵称和头像”,鉴于大家的墙裂需求,所以我最近花了点时间研究了相关解决方案,希望能跟大家一起探索。
 
运行效果




 
目标
集成环信IM的SDK后,能以最快方式,最少代码管理用户的昵称和头像。
 
解决方案
使用本地缓存(sqlite)和后端云实现头像和昵称的二级缓存
【参考】 http://docs.easemob.com/im/490integrationcases/10nickname#昵称和头像的显示与更新
 
计划
先在IOS上验证该方案的优缺点,待方案完善后,再将此模式复制到Android和WebIM上

项目快速集成
1. 按照简版Demo的方式在项目中快速集成环信IM功能

IOS快速集成环信IM - 基于官方的Demo优化,5分钟集成环信IM功能http://www.imgeek.org/article/825307886

2. 注册第三方后端云账号,使用数据存储服务





(1). 在第三方后端注册用户,进入控制台,创建应用(例如名称为【环信简版Demo】),点击【存储】按钮进入数据存储管理页面:




 
(2). 创建数据表UserWebInfo,并且按照新增三个字段(字段名开头必须小写):openId String 环信ID
nickName String 用户昵称
avatarUrl String 用户头像(绝对路径)



 
其中,avatarUrl是app端上传头像到【_File】数据表后获取到的绝对路径:





(3). 在【设置】-> 【应用Key】页面中




复制AppID和AppKey替换AppDelagate里didFinishLaunchingWithOptions的key:// 初始化web缓存配置
[UserWebManager config:launchOptions
appId:@"utUG5ot9Y64dqJIFG9Ir2rqu-gzGzoHsz"
appKey:@"IbHhNkPo4gfrFFc3epCw3eG2"];参考: 简版demo中的AppDelegate+EaseMob.m第56行
 
3. 上传用户头像和昵称到第三方后端云服务器

用户在app中调用开发者服务器API接口登录成功后,一般都会返回用户的属性信息(昵称和头像等),我们可以在这里上传用户信息到云服务器:// 登录成功后,如果后端云没有缓存用户信息,则新增一个用户
[UserWebManager createUser:username nickName:nickName avatarUrl:avatarUrl];参考:简版demo中LoginViewController.m的第156行代码
 
4.显示用户昵称和头像

在需要显示用户昵称和头像的地方,调用UserCacheManager里的方法即可,具体调用地方,请在xcode里搜索简版Demo代码“[UserCacheManager ”,如图所示,在这里就不累赘了:




 
5.修改用户昵称和头像
(1). 更改头像// 上传头像到后端云
[UserWebManager updateCurrAvatar:orgImage completed:^(UIImage *imageData) {
[weakSelf hideHud];
if(!imageData){
[self showHint:@"更新头像失败~"];
return;
}

[weakSelf.headImageView imageWithUsername:kCurrEaseUserId placeholderImage:imageData];
[self showHint:@"更新头像成功~"];
}];参考简版Demo中UserProfileEditViewController.m第181行代码
 
(2). 更新昵称[UserWebManager updateCurrNick:@"小草" completed:^(BOOL isSucc) {
if (weakSelf) {
UserProfileEditViewController *strongSelf = weakSelf;
[strongSelf hideHud];
if (isSucc) {
[strongSelf.tableView reloadData];
[strongSelf showHint:@"修改成功~"];
} else {
[strongSelf showHint:@"修改失败~" yOffset:0];
}
}
}];参考简版Demo中UserProfileEditViewController.m第152行代码
 
6.二级缓存处理流程图





 
由于能力有限,此方案难免有不妥之处,欢迎大家拍砖。





环信互帮互助-非官方 340452063
 
Q&A

问:如何安装第三方后端云存储服务 SDK?

答:安装还是比较简单的,可以参考第三方的文档,有不明白的可以看下教程 

问:使用第三方云存储服务是否稳定、安全,比如不久他关闭了app会不会受影响?

答:云服务厂商一般不会关闭,退一万步来说,即使第三方后端云停止服务了也会提前通知,我们也可以将接口换成我们开发者自己服务器的api。类似的第三方云存储服务还有MaxLeap、bmob。
 
 
 
 
 
  查看全部
最近天气转冷了,写篇文章,给大家暖暖心~

1.png

 
在环信草草群(群号:340452063)中,无论是安卓还是IOS或者WebIM,每天遇到最多的问题就是“如何显示昵称和头像”,鉴于大家的墙裂需求,所以我最近花了点时间研究了相关解决方案,希望能跟大家一起探索。
 
运行效果
2.png

 
目标
集成环信IM的SDK后,能以最快方式,最少代码管理用户的昵称和头像。
 
解决方案
使用本地缓存(sqlite)和后端云实现头像和昵称的二级缓存
【参考】 http://docs.easemob.com/im/490integrationcases/10nickname#昵称和头像的显示与更新
 
计划
先在IOS上验证该方案的优缺点,待方案完善后,再将此模式复制到Android和WebIM上

项目快速集成
1. 按照简版Demo的方式在项目中快速集成环信IM功能

IOS快速集成环信IM - 基于官方的Demo优化,5分钟集成环信IM功能http://www.imgeek.org/article/825307886

2. 注册第三方后端云账号,使用数据存储服务

3.png

(1). 在第三方后端注册用户,进入控制台,创建应用(例如名称为【环信简版Demo】),点击【存储】按钮进入数据存储管理页面:
4.png

 
(2). 创建数据表UserWebInfo,并且按照新增三个字段(字段名开头必须小写):
openId   String   环信ID
nickName String 用户昵称
avatarUrl String 用户头像(绝对路径)
5.png

 
其中,avatarUrl是app端上传头像到【_File】数据表后获取到的绝对路径:

6.png

(3). 在【设置】-> 【应用Key】页面中
7.png

复制AppID和AppKey替换AppDelagate里didFinishLaunchingWithOptions的key:
// 初始化web缓存配置
[UserWebManager config:launchOptions
appId:@"utUG5ot9Y64dqJIFG9Ir2rqu-gzGzoHsz"
appKey:@"IbHhNkPo4gfrFFc3epCw3eG2"];
参考: 简版demo中的AppDelegate+EaseMob.m第56行
 
3. 上传用户头像和昵称到第三方后端云服务器

用户在app中调用开发者服务器API接口登录成功后,一般都会返回用户的属性信息(昵称和头像等),我们可以在这里上传用户信息到云服务器:
// 登录成功后,如果后端云没有缓存用户信息,则新增一个用户
[UserWebManager createUser:username nickName:nickName avatarUrl:avatarUrl];
参考:简版demo中LoginViewController.m的第156行代码
 
4.显示用户昵称和头像

在需要显示用户昵称和头像的地方,调用UserCacheManager里的方法即可,具体调用地方,请在xcode里搜索简版Demo代码“[UserCacheManager ”,如图所示,在这里就不累赘了:
8.png

 
5.修改用户昵称和头像
(1). 更改头像
// 上传头像到后端云
[UserWebManager updateCurrAvatar:orgImage completed:^(UIImage *imageData) {
[weakSelf hideHud];
if(!imageData){
[self showHint:@"更新头像失败~"];
return;
}

[weakSelf.headImageView imageWithUsername:kCurrEaseUserId placeholderImage:imageData];
[self showHint:@"更新头像成功~"];
}];
参考简版Demo中UserProfileEditViewController.m第181行代码
 
(2). 更新昵称
[UserWebManager updateCurrNick:@"小草" completed:^(BOOL isSucc) {
if (weakSelf) {
UserProfileEditViewController *strongSelf = weakSelf;
[strongSelf hideHud];
if (isSucc) {
[strongSelf.tableView reloadData];
[strongSelf showHint:@"修改成功~"];
} else {
[strongSelf showHint:@"修改失败~" yOffset:0];
}
}
}];
参考简版Demo中UserProfileEditViewController.m第152行代码
 
6.二级缓存处理流程图

9.png

 
由于能力有限,此方案难免有不妥之处,欢迎大家拍砖。

10.png

环信互帮互助-非官方 340452063
 
Q&A

问:如何安装第三方后端云存储服务 SDK?

答:安装还是比较简单的,可以参考第三方的文档,有不明白的可以看下教程 

问:使用第三方云存储服务是否稳定、安全,比如不久他关闭了app会不会受影响?

答:云服务厂商一般不会关闭,退一万步来说,即使第三方后端云停止服务了也会提前通知,我们也可以将接口换成我们开发者自己服务器的api。类似的第三方云存储服务还有MaxLeap、bmob。
 
 
 
 
 
 
18
评论

【环信集成笔记】进阶篇-android环信昵称头像解决方法 头像和昵称 环信集成 环信_Android 头像 设置头像

陈日明 发表了文章 • 6206 次浏览 • 2016-09-27 18:43 • 来自相关话题

当你刚刚集成环信的时候,在和自己android组的小伙伴玩的不亦乐乎的时候,当你过完这把瘾的时候,那么接下来,你就要考虑的是怎么让这个头像显示的是自己想要的头像,怎么让昵称显示自己的昵称.....

那么接下来,我来告诉大家,怎么解决昵称头像的问题,

首先,这篇文章是接在我大表哥江南孤鹜在im社区写的一篇文章之后写的,上个链接地址 Android获取昵称头像接下来,我对此文章做些补充:

我看到有些人在问,这个方法放在哪里?





好吧,大表哥没说出来,这个放在UserApiModel里面

那么接下来,大表哥写的是这样的,利用扩展消息去获取头像昵称,在这里我提醒下大家,要判断这个头像是自己的还是好友的




怎么判断呢,作为新手的我们,我推荐使用shareprefences在登陆的时候保存下自己的头像昵称,然后再这里获取,并且设置给扩展





在demohelper里面有个getuserinfo方法




这里就是把获取到的头像昵称设置给环信,然后显示出来,这里最重要,切记不要写错。

那么,到此为止,其实都说完了,可是,毕竟是一个延伸,怎么可能就此结束,接下来给大家看下,请求数据,然后设置给数据库





请求的过程我就不写了,这个大家都会,获取到username,id,logo,之后先要把头像,昵称存到userdao里面,如果userdao是环信的一个数据库,这个大家自己看看demo的代码就知道了,设置到这里,是为了在联系人列表里面显示,UserInfoCacheSvc.createOrUpdate(id,username,logo_img);这句就是把头像昵称放到大表哥写的数据库里面

最后,补充一下,忘记说了,导入框架




好了,这样就结束了,如果有什么还不明白,就加入大表哥粉丝群(环信IM互帮互助群 340452063),我会帮你解答一切问题 查看全部
当你刚刚集成环信的时候,在和自己android组的小伙伴玩的不亦乐乎的时候,当你过完这把瘾的时候,那么接下来,你就要考虑的是怎么让这个头像显示的是自己想要的头像,怎么让昵称显示自己的昵称.....

那么接下来,我来告诉大家,怎么解决昵称头像的问题,

首先,这篇文章是接在我大表哥江南孤鹜在im社区写的一篇文章之后写的,上个链接地址 Android获取昵称头像接下来,我对此文章做些补充:

我看到有些人在问,这个方法放在哪里?

1.png

好吧,大表哥没说出来,这个放在UserApiModel里面

那么接下来,大表哥写的是这样的,利用扩展消息去获取头像昵称,在这里我提醒下大家,要判断这个头像是自己的还是好友的
2.png

怎么判断呢,作为新手的我们,我推荐使用shareprefences在登陆的时候保存下自己的头像昵称,然后再这里获取,并且设置给扩展

3.png

在demohelper里面有个getuserinfo方法
4.png

这里就是把获取到的头像昵称设置给环信,然后显示出来,这里最重要,切记不要写错。

那么,到此为止,其实都说完了,可是,毕竟是一个延伸,怎么可能就此结束,接下来给大家看下,请求数据,然后设置给数据库

5.png

请求的过程我就不写了,这个大家都会,获取到username,id,logo,之后先要把头像,昵称存到userdao里面,如果userdao是环信的一个数据库,这个大家自己看看demo的代码就知道了,设置到这里,是为了在联系人列表里面显示,UserInfoCacheSvc.createOrUpdate(id,username,logo_img);这句就是把头像昵称放到大表哥写的数据库里面

最后,补充一下,忘记说了,导入框架
6.png

好了,这样就结束了,如果有什么还不明白,就加入大表哥粉丝群(环信IM互帮互助群 340452063),我会帮你解答一切问题
18
评论

环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)。 头像 设置头像 头像和昵称 昵称 环信头像和昵称设置

zqbemail 发表了文章 • 12461 次浏览 • 2016-06-13 16:44 • 来自相关话题

        最近,经常有朋友问到,如何集成环信头像,怎么才能快速显示头像,因时间紧急,很多朋友都没有时间慢慢的研究代码,这里大家稍微花10分钟看一下文章,看完后再花5分钟改一下代码,即可达到你们所要的效果。
        当然这个是在你直接复制了demo中的工具类和必要的UI的前提下实现的。简短说明简单暴力的方法:除UI外的其他所有类先复制到自己工程中,UI部分MainActivity中的代码需要一个一个复制过去,如与自己项目冲突的需要调整,然后ChatActivity/ChatFragment也复制过去,这就可以进行聊天了。不过头像就是大家所遇到的头像显示不了,昵称显示为环信号码。
        环信官方是有给出头像的设置的,不过大部分朋友看了之后都是晕呼呼的。官方给出的提示如下:方法一 从APP服务器获取昵称和头像
昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求

昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二 从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像URI与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
---------------------------------------------------------------------------------------------
        个人推荐使用方法2,优势比较明显,不仅可以设置头像、昵称,甚至以后出现的是否管理员,或者自己APP中的身份标志,如:店小二、医生、客服等等都可以再定义注明,暴力而简单,不需要考虑对方更新头像或昵称,而软件没重启的情况下怎么去更新头像和昵称等等复杂的问题。本指导以最简单的集成为指导,工具类可使用自己软件中的,或通过别的方式实现。
        方法2的集成步骤:
1、在登录的时候,把自己登录成功时后台返回的信息保存到sharedpreferences中,需要包含需要的头像和昵称。new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().login(username, password, new EMCallBack() {
@Override
public void onSuccess() {
// 登陆成功,保存用户昵称与头像URL
AppSPUtils.setValueToPrefrences("name", loginBean.getName());
AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl());

// 将自己服务器返回的环信账号、昵称和头像URL设置到帮助类中。
DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName());
DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl());
DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 环信Id

// ------以下参考demo中的,加载群组和加载消息。然后跳转到首页-------2、AppSPUtils是个人写的一个工具类,大家可以自己写一个,给出参考代码。public class AppSPUtils {

private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS;

public static SharedPreferences getSharedPreferences(String name) {
return MainApplication.getContext().getSharedPreferences(name,
Context.MODE_PRIVATE | MODE_SPEC);
}

public static SharedPreferences getAppSharedPreferences() {
return getSharedPreferences(Constants.SP_APP);
}

public static String getValueFromPrefrences(String key, String defaultValue) {
return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue);
}

public static void setValueToPrefrences(String key, String value) {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != preferences) {
preferences.edit().putString(key, value).commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 退出登录时要调用
public static void clean() {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != getAppSharedPreferences()) {
getAppSharedPreferences().edit().clear().commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}3、保存好自己的信息后,已经成功了四分之一,现在是如何将自己的头像昵称等信息发送出去,最简单的就是使用扩展消息了,在ChatActivity中可以看到,基本上只做了一件事,保证只有一个ChatActivity,那我们的代码在哪里?就在ChatFragment里面。找到代码,可以看到其实它是继承自EaseChatFragment,很多内容在easeui中已经做好了。
这时你会发现ChatFragment类中有一个扩展属性的说明,没错,就是这个方法,把你要发送的内容尽情的发送吧,现附上发送头像和昵称的代码:@Override
public void onSetMessageAttributes(EMMessage message) {
if (isRobot) {
// 设置消息扩展属性
message.setAttribute("em_robot_message", isRobot);
}

// 通过扩展属性,将userPic和userName发送出去。
String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute("userPic", userPic);
}
String userName = AppSPUtils.getValueFromPrefrences("name", "");
if (!TextUtils.isEmpty(userName)) {
message.setAttribute("userName", userName);
}
}4、发送完成,你已经完成了四分之二的任务了。发送完成后,肯定需要一个接收,其实demo中的广播已经接收好了,那么我们跟随着广播的脚步,来到DemoHelper这个类,初次看这个类,都是云一样的感觉,经过一番查找,发现有个onMessageReceived的方法,并且还有注释“全局监听”,赶紧开工,试试接收吧,可以自己打一下log出来看是不是拿到了我们要的。并且照着demoHelper中的保存方法,将接收到的内容保存起来。@Override
public void onMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
message.setMsgTime(System.currentTimeMillis());
//************接收并处理扩展消息***********************
String userName = message.getStringAttribute("userName", "");
String userPic = message.getStringAttribute("userPic", "");
String hxIdFrom = message.getFrom();
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(userName);

// 存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
// 存入db
UserDao dao = new UserDao(MainApplication.getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.add(easeUser);
dao.saveContactList(users);

getModel().setContactSynced(true);

// 通知listeners联系人同步完毕
notifyContactsSyncListener(true);
if (isGroupsSyncedWithServer()) {
notifyForRecevingEvents();
}

// ******************扩展信息处理完成**********************
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
// 应用在后台,不需要刷新UI,通知栏提示新消息
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}5、信息都收到了,就差最后一步就可以显示了,不知道你们是不是激动,反正我是激动了。那在哪里进行显示呢?还是在DemoHelper中,找到getUserInfo方法,代码如下:private EaseUser getUserInfo(String hxId) {
// 获取user信息,demo是从内存的好友列表里获取,
// 实际开发中,可能还需要从服务器获取用户信息,
// 从服务器获取的数据,最好缓存起来,避免频繁的网络请求

if (hxId.equals(EMClient.getInstance().getCurrentUser())) {
EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo();
return currentUserInfo;
}
EaseUser easeUser;
if (contactList != null && contactList.containsKey(hxId)) {

} else { // 如果内存中没有,则将本地数据库中的取出到内存中。
getContactList();
}
// // TODO 获取不在好友列表里的群成员具体信息,即陌生人信息,demo未实现
// if (user == null && getRobotList() != null) {
// user = getRobotList().get(hxId);
// }
easeUser = contactList.get(hxId);
if(easeUser == null){
easeUser = new EaseUser(hxId);
} else {
if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字为空,则显示环信号码
easeUser.setNick(easeUser.getUsername());
}
}
return easeUser;
}OK,大功告成,到这里你的头像已经可以显示了。。恭喜你!
有朋友还有疑问,为什么头像是方形的,要变成圆形怎么办?指个路,在easeui中的utils包下,找到EaseUserUtils,这里就是显示用户头像和用户昵称的地方,通过Glide可以轻松显示圆形头像,百度有很多方法,这里就不多讲了,同样,你也可以通过其他图形加载框架来完成。
很多朋友不明白扩展消息的是什么东西,也不明白为什么照着代码敲就能够完成头像的显示,那下面就给大家粗浅的讲讲所涉及到的逻辑关系。
扩展消息:就是你每一次发送消息,都会附带在你发送内容上面的额外消息,他会随着你的内容发送出去,每次会多一点点流量,但微乎其微,个人认为并无多大影响。
显示头像逻辑:区分为本地化缓存和运行内存缓存,在demoHelper中可以发现,有一个成员变量private Map<String, EaseUser> contactList; 这个就是用来保存在运行内存缓存的,只有通过运行缓存,显示头像是最顺畅的,如果每次都从数据库中读取的话,聊天界面会比较卡,有朋友保存在SP里面,以ID做为KEY,头像和昵称等拼接做为value进行缓存,取出后再拆分开分别取值,据说是不卡,大家可以试一下。
         本地化存储是为了在每次打开软件的时候,从本地存储中拿到运行内存中使用做准备,大家可以认真看看demoHelper和MainActivity中的代码。

----------------------------------------------------------------------------------
讲了方法2设置头像,那么方法1,个人不推荐,但这里给出处理的过程,如有个别有需求的,可以按方法1来处理:
1、登录成功后,在手机子线程,访问你们的后台服务器,拿到所有好友的环信ID,头像,昵称。然后按上面的保存方法,保存到本地中,完成后发送广播或EventBus之类到,刷新消息界面和ChatFragment。
2、在getUserInfo中,写和上面扩展消息一样的内容,将如果运行缓存和本地都拿不到,则发起网络请求到后台获取头像,等请求到内容后,再发出广播或EventBus通知刷新消息界面和ChatFragment。

-------------------------------------------------------------------------------------
以上仅为本人在开发过程中的一点小小心得,demo中的保存运存和本地储存的方法,大家也可以单独写,并不会影响程序的运行,当然也有兄弟写过发表,大概根据实际情况择优选取即可。小弟学识浅薄,如果有错漏的,欢迎大家纠正。
如有需要,可以到494167135群中与大家交流学习。本人:乐奇奇,QQ:730326762。大家优先加群,谢谢。
  查看全部
        最近,经常有朋友问到,如何集成环信头像,怎么才能快速显示头像,因时间紧急,很多朋友都没有时间慢慢的研究代码,这里大家稍微花10分钟看一下文章,看完后再花5分钟改一下代码,即可达到你们所要的效果。
        当然这个是在你直接复制了demo中的工具类和必要的UI的前提下实现的。简短说明简单暴力的方法:除UI外的其他所有类先复制到自己工程中,UI部分MainActivity中的代码需要一个一个复制过去,如与自己项目冲突的需要调整,然后ChatActivity/ChatFragment也复制过去,这就可以进行聊天了。不过头像就是大家所遇到的头像显示不了,昵称显示为环信号码。
        环信官方是有给出头像的设置的,不过大部分朋友看了之后都是晕呼呼的。官方给出的提示如下:方法一 从APP服务器获取昵称和头像

昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求

昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二 从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像URI与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。


---------------------------------------------------------------------------------------------
        个人推荐使用方法2,优势比较明显,不仅可以设置头像、昵称,甚至以后出现的是否管理员,或者自己APP中的身份标志,如:店小二、医生、客服等等都可以再定义注明,暴力而简单,不需要考虑对方更新头像或昵称,而软件没重启的情况下怎么去更新头像和昵称等等复杂的问题。本指导以最简单的集成为指导,工具类可使用自己软件中的,或通过别的方式实现。
        方法2的集成步骤:
1、在登录的时候,把自己登录成功时后台返回的信息保存到sharedpreferences中,需要包含需要的头像和昵称。
new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().login(username, password, new EMCallBack() {
@Override
public void onSuccess() {
// 登陆成功,保存用户昵称与头像URL
AppSPUtils.setValueToPrefrences("name", loginBean.getName());
AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl());

// 将自己服务器返回的环信账号、昵称和头像URL设置到帮助类中。
DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName());
DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl());
DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 环信Id

// ------以下参考demo中的,加载群组和加载消息。然后跳转到首页-------
2、AppSPUtils是个人写的一个工具类,大家可以自己写一个,给出参考代码。
public class AppSPUtils {

private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS;

public static SharedPreferences getSharedPreferences(String name) {
return MainApplication.getContext().getSharedPreferences(name,
Context.MODE_PRIVATE | MODE_SPEC);
}

public static SharedPreferences getAppSharedPreferences() {
return getSharedPreferences(Constants.SP_APP);
}

public static String getValueFromPrefrences(String key, String defaultValue) {
return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue);
}

public static void setValueToPrefrences(String key, String value) {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != preferences) {
preferences.edit().putString(key, value).commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 退出登录时要调用
public static void clean() {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != getAppSharedPreferences()) {
getAppSharedPreferences().edit().clear().commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、保存好自己的信息后,已经成功了四分之一,现在是如何将自己的头像昵称等信息发送出去,最简单的就是使用扩展消息了,在ChatActivity中可以看到,基本上只做了一件事,保证只有一个ChatActivity,那我们的代码在哪里?就在ChatFragment里面。找到代码,可以看到其实它是继承自EaseChatFragment,很多内容在easeui中已经做好了。
这时你会发现ChatFragment类中有一个扩展属性的说明,没错,就是这个方法,把你要发送的内容尽情的发送吧,现附上发送头像和昵称的代码:
@Override
public void onSetMessageAttributes(EMMessage message) {
if (isRobot) {
// 设置消息扩展属性
message.setAttribute("em_robot_message", isRobot);
}

// 通过扩展属性,将userPic和userName发送出去。
String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute("userPic", userPic);
}
String userName = AppSPUtils.getValueFromPrefrences("name", "");
if (!TextUtils.isEmpty(userName)) {
message.setAttribute("userName", userName);
}
}
4、发送完成,你已经完成了四分之二的任务了。发送完成后,肯定需要一个接收,其实demo中的广播已经接收好了,那么我们跟随着广播的脚步,来到DemoHelper这个类,初次看这个类,都是云一样的感觉,经过一番查找,发现有个onMessageReceived的方法,并且还有注释“全局监听”,赶紧开工,试试接收吧,可以自己打一下log出来看是不是拿到了我们要的。并且照着demoHelper中的保存方法,将接收到的内容保存起来。
@Override
public void onMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
message.setMsgTime(System.currentTimeMillis());
//************接收并处理扩展消息***********************
String userName = message.getStringAttribute("userName", "");
String userPic = message.getStringAttribute("userPic", "");
String hxIdFrom = message.getFrom();
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(userName);

// 存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
// 存入db
UserDao dao = new UserDao(MainApplication.getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.add(easeUser);
dao.saveContactList(users);

getModel().setContactSynced(true);

// 通知listeners联系人同步完毕
notifyContactsSyncListener(true);
if (isGroupsSyncedWithServer()) {
notifyForRecevingEvents();
}

// ******************扩展信息处理完成**********************
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
// 应用在后台,不需要刷新UI,通知栏提示新消息
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}
5、信息都收到了,就差最后一步就可以显示了,不知道你们是不是激动,反正我是激动了。那在哪里进行显示呢?还是在DemoHelper中,找到getUserInfo方法,代码如下:
private EaseUser getUserInfo(String hxId) {
// 获取user信息,demo是从内存的好友列表里获取,
// 实际开发中,可能还需要从服务器获取用户信息,
// 从服务器获取的数据,最好缓存起来,避免频繁的网络请求

if (hxId.equals(EMClient.getInstance().getCurrentUser())) {
EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo();
return currentUserInfo;
}
EaseUser easeUser;
if (contactList != null && contactList.containsKey(hxId)) {

} else { // 如果内存中没有,则将本地数据库中的取出到内存中。
getContactList();
}
// // TODO 获取不在好友列表里的群成员具体信息,即陌生人信息,demo未实现
// if (user == null && getRobotList() != null) {
// user = getRobotList().get(hxId);
// }
easeUser = contactList.get(hxId);
if(easeUser == null){
easeUser = new EaseUser(hxId);
} else {
if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字为空,则显示环信号码
easeUser.setNick(easeUser.getUsername());
}
}
return easeUser;
}
OK,大功告成,到这里你的头像已经可以显示了。。恭喜你!
有朋友还有疑问,为什么头像是方形的,要变成圆形怎么办?指个路,在easeui中的utils包下,找到EaseUserUtils,这里就是显示用户头像和用户昵称的地方,通过Glide可以轻松显示圆形头像,百度有很多方法,这里就不多讲了,同样,你也可以通过其他图形加载框架来完成。
很多朋友不明白扩展消息的是什么东西,也不明白为什么照着代码敲就能够完成头像的显示,那下面就给大家粗浅的讲讲所涉及到的逻辑关系。
扩展消息:就是你每一次发送消息,都会附带在你发送内容上面的额外消息,他会随着你的内容发送出去,每次会多一点点流量,但微乎其微,个人认为并无多大影响。
显示头像逻辑:区分为本地化缓存和运行内存缓存,在demoHelper中可以发现,有一个成员变量private Map<String, EaseUser> contactList; 这个就是用来保存在运行内存缓存的,只有通过运行缓存,显示头像是最顺畅的,如果每次都从数据库中读取的话,聊天界面会比较卡,有朋友保存在SP里面,以ID做为KEY,头像和昵称等拼接做为value进行缓存,取出后再拆分开分别取值,据说是不卡,大家可以试一下。
         本地化存储是为了在每次打开软件的时候,从本地存储中拿到运行内存中使用做准备,大家可以认真看看demoHelper和MainActivity中的代码。

----------------------------------------------------------------------------------
讲了方法2设置头像,那么方法1,个人不推荐,但这里给出处理的过程,如有个别有需求的,可以按方法1来处理:
1、登录成功后,在手机子线程,访问你们的后台服务器,拿到所有好友的环信ID,头像,昵称。然后按上面的保存方法,保存到本地中,完成后发送广播或EventBus之类到,刷新消息界面和ChatFragment。
2、在getUserInfo中,写和上面扩展消息一样的内容,将如果运行缓存和本地都拿不到,则发起网络请求到后台获取头像,等请求到内容后,再发出广播或EventBus通知刷新消息界面和ChatFragment。

-------------------------------------------------------------------------------------
以上仅为本人在开发过程中的一点小小心得,demo中的保存运存和本地储存的方法,大家也可以单独写,并不会影响程序的运行,当然也有兄弟写过发表,大概根据实际情况择优选取即可。小弟学识浅薄,如果有错漏的,欢迎大家纠正。
如有需要,可以到494167135群中与大家交流学习。本人:乐奇奇,QQ:730326762。大家优先加群,谢谢。
 
33
评论

android中如何显示开发者服务器上的昵称和头像 头像 设置头像 头像和昵称的显示 昵称 头像自定义

江南孤鹜 发表了文章 • 19970 次浏览 • 2016-05-25 15:19 • 来自相关话题

本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757
无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际应用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:





那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490 ... kname
 
引用一下关键文字:方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。
昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
 
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);
 
关键代码:/***************** 环信用户缓存信息 *******************************/
public static final String ChatUserId = "ChatUserId";// 用户的环信ID
public static final String ChatUserPic = "ChatUserPic";
public static final String ChatUserNick = "ChatUserNick";
/***************** 环信用户缓存信息***********end ********************/



UserInfoCacheSvc.java是环信用户信息缓存管理类/**
* 缓存用户信息(主要用于聊天显示昵称和头像)
*/
public class UserInfoCacheSvc {
public static List<UserApiModel> getAllList(){
Dao<UserApiModel, Integer> daoScene = SqliteHelper.getInstance().getUserDao();
try {
List<UserApiModel> list = daoScene.queryBuilder().query();
return list;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getByChatUserName(String chatUserName){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("EaseMobUserName", chatUserName).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static boolean createOrUpdate(String chatUserName, String userNickName, String avatarUrl){
try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getByChatUserName(chatUserName);

int changedLines = 0;
if (user == null){
user = new UserApiModel();
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.create(user);
}else {
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.update(user);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

public static boolean createOrUpdate(UserApiModel model){

if(model == null) return false;

try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getById(model.Id);

if (!StringUtils.isNullOrEmpty(model.getHeadImg())){
String fullPath = "http://image.baidu.com" + model.getHeadImg();
//特别注意:这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

model.setHeadImg(fullPath);
}
int changedLines = 0;
if (user == null){
changedLines = dao.create(model);
}else {
model.setRecordId(user.getRecordId());
changedLines = dao.update(model);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

}首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:public class UserApiModel implements Serializable {

@DatabaseField(generatedId=true)
private int RecordId;

@DatabaseField

public long Id;

@DatabaseField
public String Username;

@DatabaseField
public String Email;

@DatabaseField
public String HeadImg;

@DatabaseField
public String EaseMobUserName;

@DatabaseField
public String EaseMobPassword;
} private static void SaveUserInfo(UserApiModel userInfo){

if(userInfo == null) return;

// 缓存用户信息
PrefUtils.setUserId(userInfo.Id);
PrefUtils.setUserEmail(userInfo.Email);
PrefUtils.setUserName(userInfo.Username);
PrefUtils.setUserPic(userInfo.HeadImg);
PrefUtils.setUserChatId(userInfo.EaseMobUserName);
PrefUtils.setUserChatPwd(userInfo.EaseMobPassword);

UserInfoCacheSvc.createOrUpdate(userInfo);
}然后在接收环信消息的回调函数里保存用户信息,ActyMain.java是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:private EMMessageListener mMessageListener = new EMMessageListener() {

@Override
public void onMessageReceived(List<EMMessage> messages) {
// 提示新消息
for (EMMessage message : messages) {

// 先将头像和昵称保存在本地缓存
try {
String chatUserId = message.getStringAttribute(SharePrefConstant.ChatUserId);
String avatarUrl = message.getStringAttribute(SharePrefConstant.ChatUserPic);
String nickName = message.getStringAttribute(SharePrefConstant.ChatUserNick);

UserInfoCacheSvc.createOrUpdate(chatUserId, nickName, avatarUrl);

} catch (HyphenateException e) {
e.printStackTrace();
}

ChatHelper.getInstance().getNotifier().onNewMsg(message);
}
refreshUIWithMessage();
}

// 此处省略N行代码....
};在安卓项目里,环信页面显示昵称和头像时,都会统一从DemoHelper的getUserInfo函数里获取信息,所以我们要在这里从缓存取用户头像和昵称:private EaseUser getUserInfo(String username){
//获取user信息,demo是从内存的好友列表里获取,
//实际开发中,可能还需要从服务器获取用户信息,
//从服务器获取的数据,最好缓存起来,避免频繁的网络请求
EaseUser user = null;
// 从缓存里取昵称和头像
UserApiModel userInfo = UserInfoCacheSvc.getByChatUserName(username);
if (userInfo != null){
user = new EaseUser(username);
user.setAvatar(userInfo.getHeadImg());
user.setNick(userInfo.getUsername());
}

return user;
}最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在
ChatFragment.java里: @Override
public void onSetMessageAttributes(EMMessage message) {
setUserInfoAttribute(message);
}

/**
* 设置用户的属性,
* 通过消息的扩展,传递客服系统用户的属性信息
* @param message
*/
private void setUserInfoAttribute(EMMessage message) {
try {
message.setAttribute(SharePrefConstant.ChatUserId, PrefUtils.getUserChatId());
message.setAttribute(SharePrefConstant.ChatUserNick, PrefUtils.getUserName());
message.setAttribute(SharePrefConstant.ChatUserPic, "http://image.baidu.com" + PrefUtils.getUserPic()) ;//这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

} catch (Exception e) {
e.printStackTrace();
}
}有不当之处,欢迎指正~~~谢谢
部分源码因为是公司项目代码,所以没有在文章里提供(而且代码量太多,也不便于阅读)。需要源码的童鞋,可以联系我。等我有空,我整理一下公司项目,然后再share开源给大家。
相关类文件下载:

EaseUI头像和昵称相关类文件_0701.zip


 
本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757
如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063,
或者加本人QQ:364223587,加Q请认准以下正宗小马头像: 查看全部

本文方法已经废弃!请看作者另外一篇文章:


在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757


无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际应用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:
444.png


那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490 ... kname
 
引用一下关键文字:
方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。
昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
 
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);
 
关键代码:
/***************** 环信用户缓存信息 *******************************/
public static final String ChatUserId = "ChatUserId";// 用户的环信ID
public static final String ChatUserPic = "ChatUserPic";
public static final String ChatUserNick = "ChatUserNick";
/***************** 环信用户缓存信息***********end ********************/



UserInfoCacheSvc.java是环信用户信息缓存管理类
/**
* 缓存用户信息(主要用于聊天显示昵称和头像)
*/
public class UserInfoCacheSvc {
public static List<UserApiModel> getAllList(){
Dao<UserApiModel, Integer> daoScene = SqliteHelper.getInstance().getUserDao();
try {
List<UserApiModel> list = daoScene.queryBuilder().query();
return list;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getByChatUserName(String chatUserName){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("EaseMobUserName", chatUserName).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static boolean createOrUpdate(String chatUserName, String userNickName, String avatarUrl){
try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getByChatUserName(chatUserName);

int changedLines = 0;
if (user == null){
user = new UserApiModel();
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.create(user);
}else {
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.update(user);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

public static boolean createOrUpdate(UserApiModel model){

if(model == null) return false;

try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getById(model.Id);

if (!StringUtils.isNullOrEmpty(model.getHeadImg())){
String fullPath = "http://image.baidu.com" + model.getHeadImg();
//特别注意:这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

model.setHeadImg(fullPath);
}
int changedLines = 0;
if (user == null){
changedLines = dao.create(model);
}else {
model.setRecordId(user.getRecordId());
changedLines = dao.update(model);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

}
首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:
public class UserApiModel implements Serializable {

@DatabaseField(generatedId=true)
private int RecordId;

@DatabaseField

public long Id;

@DatabaseField
public String Username;

@DatabaseField
public String Email;

@DatabaseField
public String HeadImg;

@DatabaseField
public String EaseMobUserName;

@DatabaseField
public String EaseMobPassword;
}
 
private static void SaveUserInfo(UserApiModel userInfo){

if(userInfo == null) return;

// 缓存用户信息
PrefUtils.setUserId(userInfo.Id);
PrefUtils.setUserEmail(userInfo.Email);
PrefUtils.setUserName(userInfo.Username);
PrefUtils.setUserPic(userInfo.HeadImg);
PrefUtils.setUserChatId(userInfo.EaseMobUserName);
PrefUtils.setUserChatPwd(userInfo.EaseMobPassword);

UserInfoCacheSvc.createOrUpdate(userInfo);
}
然后在接收环信消息的回调函数里保存用户信息,ActyMain.java是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:
private EMMessageListener mMessageListener = new EMMessageListener() {

@Override
public void onMessageReceived(List<EMMessage> messages) {
// 提示新消息
for (EMMessage message : messages) {

// 先将头像和昵称保存在本地缓存
try {
String chatUserId = message.getStringAttribute(SharePrefConstant.ChatUserId);
String avatarUrl = message.getStringAttribute(SharePrefConstant.ChatUserPic);
String nickName = message.getStringAttribute(SharePrefConstant.ChatUserNick);

UserInfoCacheSvc.createOrUpdate(chatUserId, nickName, avatarUrl);

} catch (HyphenateException e) {
e.printStackTrace();
}

ChatHelper.getInstance().getNotifier().onNewMsg(message);
}
refreshUIWithMessage();
}

// 此处省略N行代码....
};
在安卓项目里,环信页面显示昵称和头像时,都会统一从DemoHelper的getUserInfo函数里获取信息,所以我们要在这里从缓存取用户头像和昵称:
private EaseUser getUserInfo(String username){
//获取user信息,demo是从内存的好友列表里获取,
//实际开发中,可能还需要从服务器获取用户信息,
//从服务器获取的数据,最好缓存起来,避免频繁的网络请求
EaseUser user = null;
// 从缓存里取昵称和头像
UserApiModel userInfo = UserInfoCacheSvc.getByChatUserName(username);
if (userInfo != null){
user = new EaseUser(username);
user.setAvatar(userInfo.getHeadImg());
user.setNick(userInfo.getUsername());
}

return user;
}
最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在
ChatFragment.java里:
    @Override
public void onSetMessageAttributes(EMMessage message) {
setUserInfoAttribute(message);
}

/**
* 设置用户的属性,
* 通过消息的扩展,传递客服系统用户的属性信息
* @param message
*/
private void setUserInfoAttribute(EMMessage message) {
try {
message.setAttribute(SharePrefConstant.ChatUserId, PrefUtils.getUserChatId());
message.setAttribute(SharePrefConstant.ChatUserNick, PrefUtils.getUserName());
message.setAttribute(SharePrefConstant.ChatUserPic, "http://image.baidu.com" + PrefUtils.getUserPic()) ;//这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

} catch (Exception e) {
e.printStackTrace();
}
}
有不当之处,欢迎指正~~~谢谢
部分源码因为是公司项目代码,所以没有在文章里提供(而且代码量太多,也不便于阅读)。需要源码的童鞋,可以联系我。等我有空,我整理一下公司项目,然后再share开源给大家。
相关类文件下载:

 
本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063,
或者加本人QQ:364223587,加Q请认准以下正宗小马头像:


10
评论

IOS中如何显示开发者服务器上的昵称和头像 头像 头像自定义 头像和昵称 设置头像 头像 昵称 扩展

江南孤鹜 发表了文章 • 45981 次浏览 • 2016-05-25 14:49 • 来自相关话题

无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际运用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:




 
那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490integrationcases/10nickname
 
引用一下关键文字:
方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);

 
IOS关键代码:// 环信聊天用的昵称和头像(发送聊天消息时,要附带这3个属性)
#define kChatUserId @"ChatUserId"// 环信账号
#define kChatUserNick @"ChatUserNick"
#define kChatUserPic @"ChatUserPic"
 ChatUserCacheInfo是环信用户信息缓存管理类
ChatUserCacheInfo.h#import <Foundation/Foundation.h>

@interface ChatUserCacheInfo : NSObject
@property(nonatomic,copy)NSString* Id;
@property(nonatomic,copy)NSString* NickName;
@property(nonatomic,copy)NSString* AvatarUrl;
@end


@interface ChatUserCacheUtil : NSObject

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName;

+(void)saveDict:(NSDictionary *)userinfo;

+(void)saveModel:(UserApiModel*)user;

+(ChatUserCacheInfo*)queryById:(NSString *)userid;

@end









ChatUserCacheUtil.m#import "ChatUserCacheUtil.h"
#import "FMDB.h"

#define DBNAME @"cache_data.db"

@implementation ChatUserCacheInfo

@end

@implementation ChatUserCacheUtil

+(void)createTable:(FMDatabase *)db
{
if ([db open]) {
if (![db tableExists :@"userinfo"]) {
if ([db executeUpdate:@"create table userinfo (userid text, username text, userimage text)"]) {
NSLog(@"create table success");
}else{
NSLog(@"fail to create table");
}
}else {
NSLog(@"table is already exist");
}
}else{
NSLog(@"fail to open");
}
}

+ (void)clearTableData:(FMDatabase *)db
{
if ([db executeUpdate:@"DELETE FROM userinfo"]) {
NSLog(@"clear successed");
}else{
NSLog(@"fail to clear");
}
}

+(FMDatabase*)getDB{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:DBNAME];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
[self createTable:db];
return db;
}

+(void)saveModel:(UserApiModel*)user{
[ChatUserCacheUtil saveInfo:user.EaseMobUserName imgId:user.HeadImg nickName:user.Username];
}

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName{
NSMutableDictionary *extDic = [NSMutableDictionary dictionary];
[extDic setValue:openId forKey:kChatUserId];
[extDic setValue:@"[url=http://img.baidu.com"]http://img.baidu.com/"[/url]+imgId forKey:kChatUserPic];//完整图片路径"http://img.baidu.com/1234"。如果imgId是相对路径,那完整路径就是类似"http://img.baidu.com/abc.jpg"
[extDic setValue:nickName forKey:kChatUserNick];
[ChatUserCacheUtil saveDict:extDic];
}

+(void)saveDict:(NSDictionary *)userinfo{
FMDatabase *db = [self getDB];

NSString *userid = [userinfo objectForKey:kChatUserId];
if ([db executeUpdate:@"DELETE FROM userinfo where userid = ?", userid]) {
DLog(@"删除成功");
}else{
DLog(@"删除失败");
}
NSString *username = [userinfo objectForKey:kChatUserNick];
NSString *userimage = [userinfo objectForKey:kChatUserPic];
if ([db executeUpdate:@"INSERT INTO userinfo (userid, username, userimage) VALUES (?, ?, ?)", userid,username,userimage]) {
DLog(@"插入成功");
}else{
DLog(@"插入失败");
}

// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@ %@ %@",userid,username,userimage);
}

rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo"];
while ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询所有 %@ %@ %@",userid,username,userimage);
}
[rs close];
// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
[db close];

}

+(ChatUserCacheInfo*)queryById:(NSString *)userid{
FMDatabase *db = [self getDB];
if ([db open]) {
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {

ChatUserCacheInfo *userInfo = [[ChatUserCacheInfo alloc] init];

userInfo.Id = [rs stringForColumn:@"userid"];
userInfo.NickName = [rs stringForColumn:@"username"];
userInfo.AvatarUrl = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@",userInfo);
return userInfo;
}else{
return nil;
}
}else{
return nil;
}
}


@end首先要在用户登录或注册成功后,返回用户登录信息时,缓存一下用户信息:@protocol UserApiModel <NSObject>

@end

@interface UserApiModel : BaseJSONModel
@property(nonatomic, assign)int Id;
@property(nonatomic, copy)NSString *Username;
@property(nonatomic, copy)NSString *Email;
@property(nonatomic, copy)NSString *HeadImg;
@property(nonatomic, copy)NSString *EaseMobUserName;
@property(nonatomic, copy)NSString *EaseMobPassword;
@end

// 登录成功后返回用户model,需要为环信聊天窗口缓存用户信息
[ChatUserCacheUtil saveModel:user];
然后在接收环信消息的回调函数里保存用户信息,HsMainViewController.m是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:// 收到消息回调
-(void) didReceiveMessage:(EMMessage *)message
{
[ChatUserCacheUtil saveDict:message.ext];

BOOL needShowNotification = (message.messageType != eMessageTypeChat) ? [self needShowNotification:message.conversationChatter] : YES;
if (needShowNotification) {
#if !TARGET_IPHONE_SIMULATOR

BOOL isAppActivity = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
if (!isAppActivity) {
[self showNotificationWithMessage:message];
}else {
[self playSoundAndVibration];
}
#endif
}
}环信页面主要是在ChatViewController和ConversationListViewController里显示用户对话,所以我们要在这两个页面里从缓存取用户头像和昵称,先从ChatViewController开始:- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
id<IMessageModel> model = [[EaseMessageModel alloc] initWithMessage:message];

ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.nickname];
if (userinfo != nil) {
model.nickname = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
model.failImageName = @"imageDownloadFail";

return model;
}然后是ConversationListViewController:#pragma mark - EaseConversationListViewControllerDataSource

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
modelForConversation:(EMConversation *)conversation
{
EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
if (model.conversation.conversationType == eConversationTypeChat) {
ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.conversation.chatter];
if (userinfo != nil) {
model.title = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}
model.avatarImage = PlaceholderImgChatUser;
} else if (model.conversation.conversationType == eConversationTypeGroupChat) {
// 此处省略100行代码........
}
}最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在EaseSDKHelper.m里:// 重新消息扩展组织
+(NSMutableDictionary*)reGetMessageExt:(NSDictionary *)messageExt{
NSMutableDictionary *extDic = [NSMutableDictionary dictionaryWithDictionary:messageExt];
[extDic setValue:[SettingData share].UserChatId forKey:kChatUserId];
[extDic setValue:[SettingData share].UserHeadImg.ServerThumbUrlStr forKey:kChatUserPic];
[extDic setValue:[SettingData share].UserName forKey:kChatUserNick];
return extDic;
}

+ (EMMessage *)sendTextMessage:(NSString *)text
to:(NSString *)toUser
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt

{
// 表情映射。
NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:text];
EMChatText *textChat = [[EMChatText alloc] initWithText:willSendText];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:textChat];
EMMessage *message = [[EMMessage alloc] initWithReceiver:toUser bodies:[NSArray arrayWithObject:body]];
message.requireEncryption = requireEncryption;
message.messageType = messageType;

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:nil];

return retMessage;
}


+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
return [self sendImageMessageWithImage:image to:to messageType:messageType requireEncryption:requireEncryption messageExt:messageExt quality:0.6 progress:progress];
}

+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
quality:(float)quality
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略9行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVoiceMessageWithLocalPath:(NSString *)localPath
duration:(NSInteger)duration
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVideoMessageWithURL:(NSURL *)url
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendFileMessage:(EMChatFile *)chatFile
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}
有不当之处,欢迎指正~~谢谢。QQ:364223587
 
以上代码为SDK V2版本,如果集成的是V3版本,请移步源码:
http://git.oschina.net/markies/ChatDemo-UI3.00-Simple
思路其实跟V2差不多,最大区别V3的回调方法didReceiveMessages比V2多了个【s】。

ChatUserCacheUtil我已经重命名为:UserCacheManager
 

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063
  查看全部
无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际运用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:
1.png

 
那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490integrationcases/10nickname
 
引用一下关键文字:

方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。


 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);

 
IOS关键代码:
// 环信聊天用的昵称和头像(发送聊天消息时,要附带这3个属性)
#define kChatUserId @"ChatUserId"// 环信账号
#define kChatUserNick @"ChatUserNick"
#define kChatUserPic @"ChatUserPic"

 ChatUserCacheInfo是环信用户信息缓存管理类
ChatUserCacheInfo.h
#import <Foundation/Foundation.h>

@interface ChatUserCacheInfo : NSObject
@property(nonatomic,copy)NSString* Id;
@property(nonatomic,copy)NSString* NickName;
@property(nonatomic,copy)NSString* AvatarUrl;
@end


@interface ChatUserCacheUtil : NSObject

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName;

+(void)saveDict:(NSDictionary *)userinfo;

+(void)saveModel:(UserApiModel*)user;

+(ChatUserCacheInfo*)queryById:(NSString *)userid;

@end









ChatUserCacheUtil.m
#import "ChatUserCacheUtil.h"
#import "FMDB.h"

#define DBNAME @"cache_data.db"

@implementation ChatUserCacheInfo

@end

@implementation ChatUserCacheUtil

+(void)createTable:(FMDatabase *)db
{
if ([db open]) {
if (![db tableExists :@"userinfo"]) {
if ([db executeUpdate:@"create table userinfo (userid text, username text, userimage text)"]) {
NSLog(@"create table success");
}else{
NSLog(@"fail to create table");
}
}else {
NSLog(@"table is already exist");
}
}else{
NSLog(@"fail to open");
}
}

+ (void)clearTableData:(FMDatabase *)db
{
if ([db executeUpdate:@"DELETE FROM userinfo"]) {
NSLog(@"clear successed");
}else{
NSLog(@"fail to clear");
}
}

+(FMDatabase*)getDB{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:DBNAME];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
[self createTable:db];
return db;
}

+(void)saveModel:(UserApiModel*)user{
[ChatUserCacheUtil saveInfo:user.EaseMobUserName imgId:user.HeadImg nickName:user.Username];
}

+(void)saveInfo:(NSString *)openId
imgId:(NSString*)imgId
nickName:(NSString*)nickName{
NSMutableDictionary *extDic = [NSMutableDictionary dictionary];
[extDic setValue:openId forKey:kChatUserId];
[extDic setValue:@"[url=http://img.baidu.com"]http://img.baidu.com/"[/url]+imgId forKey:kChatUserPic];//完整图片路径"http://img.baidu.com/1234"。如果imgId是相对路径,那完整路径就是类似"http://img.baidu.com/abc.jpg"
[extDic setValue:nickName forKey:kChatUserNick];
[ChatUserCacheUtil saveDict:extDic];
}

+(void)saveDict:(NSDictionary *)userinfo{
FMDatabase *db = [self getDB];

NSString *userid = [userinfo objectForKey:kChatUserId];
if ([db executeUpdate:@"DELETE FROM userinfo where userid = ?", userid]) {
DLog(@"删除成功");
}else{
DLog(@"删除失败");
}
NSString *username = [userinfo objectForKey:kChatUserNick];
NSString *userimage = [userinfo objectForKey:kChatUserPic];
if ([db executeUpdate:@"INSERT INTO userinfo (userid, username, userimage) VALUES (?, ?, ?)", userid,username,userimage]) {
DLog(@"插入成功");
}else{
DLog(@"插入失败");
}

// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@ %@ %@",userid,username,userimage);
}

rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo"];
while ([rs next]) {
NSString *userid = [rs stringForColumn:@"userid"];
NSString *username = [rs stringForColumn:@"username"];
NSString *userimage = [rs stringForColumn:@"userimage"];
DLog(@"查询所有 %@ %@ %@",userid,username,userimage);
}
[rs close];
// NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
[db close];

}

+(ChatUserCacheInfo*)queryById:(NSString *)userid{
FMDatabase *db = [self getDB];
if ([db open]) {
FMResultSet *rs = [db executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid];
if ([rs next]) {

ChatUserCacheInfo *userInfo = [[ChatUserCacheInfo alloc] init];

userInfo.Id = [rs stringForColumn:@"userid"];
userInfo.NickName = [rs stringForColumn:@"username"];
userInfo.AvatarUrl = [rs stringForColumn:@"userimage"];
DLog(@"查询一个 %@",userInfo);
return userInfo;
}else{
return nil;
}
}else{
return nil;
}
}


@end
首先要在用户登录或注册成功后,返回用户登录信息时,缓存一下用户信息:
@protocol UserApiModel <NSObject>

@end

@interface UserApiModel : BaseJSONModel
@property(nonatomic, assign)int Id;
@property(nonatomic, copy)NSString *Username;
@property(nonatomic, copy)NSString *Email;
@property(nonatomic, copy)NSString *HeadImg;
@property(nonatomic, copy)NSString *EaseMobUserName;
@property(nonatomic, copy)NSString *EaseMobPassword;
@end

// 登录成功后返回用户model,需要为环信聊天窗口缓存用户信息
[ChatUserCacheUtil saveModel:user];

然后在接收环信消息的回调函数里保存用户信息,HsMainViewController.m是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:
// 收到消息回调
-(void) didReceiveMessage:(EMMessage *)message
{
[ChatUserCacheUtil saveDict:message.ext];

BOOL needShowNotification = (message.messageType != eMessageTypeChat) ? [self needShowNotification:message.conversationChatter] : YES;
if (needShowNotification) {
#if !TARGET_IPHONE_SIMULATOR

BOOL isAppActivity = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
if (!isAppActivity) {
[self showNotificationWithMessage:message];
}else {
[self playSoundAndVibration];
}
#endif
}
}
环信页面主要是在ChatViewController和ConversationListViewController里显示用户对话,所以我们要在这两个页面里从缓存取用户头像和昵称,先从ChatViewController开始:
- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
id<IMessageModel> model = [[EaseMessageModel alloc] initWithMessage:message];

ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.nickname];
if (userinfo != nil) {
model.nickname = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}

model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
model.failImageName = @"imageDownloadFail";

return model;
}
然后是ConversationListViewController:
#pragma mark - EaseConversationListViewControllerDataSource

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
modelForConversation:(EMConversation *)conversation
{
EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
if (model.conversation.conversationType == eConversationTypeChat) {
ChatUserCacheInfo *userinfo = [ChatUserCacheUtil queryById:model.conversation.chatter];
if (userinfo != nil) {
model.title = userinfo.NickName;
model.avatarURLPath = userinfo.AvatarUrl;
}
model.avatarImage = PlaceholderImgChatUser;
} else if (model.conversation.conversationType == eConversationTypeGroupChat) {
// 此处省略100行代码........
}
}
最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在EaseSDKHelper.m里:
// 重新消息扩展组织
+(NSMutableDictionary*)reGetMessageExt:(NSDictionary *)messageExt{
NSMutableDictionary *extDic = [NSMutableDictionary dictionaryWithDictionary:messageExt];
[extDic setValue:[SettingData share].UserChatId forKey:kChatUserId];
[extDic setValue:[SettingData share].UserHeadImg.ServerThumbUrlStr forKey:kChatUserPic];
[extDic setValue:[SettingData share].UserName forKey:kChatUserNick];
return extDic;
}

+ (EMMessage *)sendTextMessage:(NSString *)text
to:(NSString *)toUser
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt

{
// 表情映射。
NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:text];
EMChatText *textChat = [[EMChatText alloc] initWithText:willSendText];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:textChat];
EMMessage *message = [[EMMessage alloc] initWithReceiver:toUser bodies:[NSArray arrayWithObject:body]];
message.requireEncryption = requireEncryption;
message.messageType = messageType;

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:nil];

return retMessage;
}


+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
return [self sendImageMessageWithImage:image to:to messageType:messageType requireEncryption:requireEncryption messageExt:messageExt quality:0.6 progress:progress];
}

+ (EMMessage *)sendImageMessageWithImage:(UIImage *)image
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
quality:(float)quality
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略9行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVoiceMessageWithLocalPath:(NSString *)localPath
duration:(NSInteger)duration
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendVideoMessageWithURL:(NSURL *)url
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

+ (EMMessage *)sendFileMessage:(EMChatFile *)chatFile
to:(NSString *)to
messageType:(EMMessageType)messageType
requireEncryption:(BOOL)requireEncryption
messageExt:(NSDictionary *)messageExt
progress:(id<IEMChatProgressDelegate>)progress
{
// 此处省略4行代码....

message.ext = [self reGetMessageExt:messageExt];
EMMessage *retMessage = [[EaseMob sharedInstance].chatManager asyncSendMessage:message
progress:progress];

return retMessage;
}

有不当之处,欢迎指正~~谢谢。QQ:364223587
 
以上代码为SDK V2版本,如果集成的是V3版本,请移步源码:
http://git.oschina.net/markies/ChatDemo-UI3.00-Simple
思路其实跟V2差不多,最大区别V3的回调方法didReceiveMessages比V2多了个【s】。

ChatUserCacheUtil我已经重命名为:UserCacheManager
 

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063