问题是这样的,服务器端注册环信账号时,设置了昵称,但是在 APP 客户端却怎么也读取不到,而环信的管理后台却可以看到用户昵称。
查了一下,发现环信服务端并不给其 SDK 提供昵称。。。环信这群垃圾!
基本的实现思路是,在 weex js 端拉取自己服务器中的联系人列表,然后通过 storage module 与 native 代码共享联系人昵称。
这个过程需要阅读 weex sdk storage 以及 EaseUI 的实现代码,不得不说 weex 与环信的文档都写得非常不认真,遗漏了诸多细节,只能自己查看源代码,差评。
Android 获取用户昵称的实现
在调用 EaseUI.getInstance().init 初始化之后去设置用户信息提供者
EaseUI easeUI = EaseUI.getInstance();
easeUI.setUserProfileProvider(new EaseUserProfileProvider() {
@Override
public EaseUser getUser(String username) {
return getUserInfo(username);
}
});
需要注意的是,getUserInfo 是自己定义的函数。即,自己提供 id 与昵称的映射关系。
翻看了环信 SDK 的源代码,确认了这种方式是可行的。
EaseUI EaseUserUtils 类的实现
public static EaseUser getUserInfo(String username){
if(userProvider != null)
return userProvider.getUser(username);
return null;
}
EaseChatFragment.java 的实现
// set title
if(EaseUserUtils.getUserInfo(toChatUsername) != null){
EaseUser user = EaseUserUtils.getUserInfo(toChatUsername);
if (user != null) {
titleBar.setTitle(user.getNick());
}
}
可见,的确需要自己去实现 getUserInfo 这个函数。
实现的思路,在 Weex 中使用 js 每次拉取联系人成功之后,存储到 storage 中。然后,原生 native 代码从 storage 取出这些联系人信息即可。
Android
private EaseUser getUserInfo(String username) {
EaseUser easeUser = new EaseUser(username);
easeUser.setNickname(nickname);
return easeUser;
}
从 weex 的实现 WXSQLiteOpenHelper.java 看
private static final String STATEMENT_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_STORAGE + " ("
+ COLUMN_KEY
+ " TEXT PRIMARY KEY,"
+ COLUMN_VALUE
+ " TEXT NOT NULL,"
+ COLUMN_TIMESTAMP
+ " TEXT NOT NULL,"
+ COLUMN_PERSISTENT
+ " INTEGER DEFAULT 0"
+ ")";
weex 是自己建立了一个指定名字的 sqlite 数据表
Android 读取 weex storage module 中存储的内容的实现
private EaseUser getUserInfo(String username) {
EaseUser easeUser = new EaseUser(username);
String nickname = performGetItem("chat_" + username.toLowerCase());
if (nickname == null) {
nickname = "烟台开发区地头蛇";
}
easeUser.setNickname(nickname);
return easeUser;
}
private String performGetItem(String key) {
SQLiteDatabase database = mDatabaseSupplier.getDatabase();
if (database == null) {
return null;
}
Cursor c = database.query("default_wx_storage",
new String[]{"value"},
"key" + "=?",
new String[]{key},
null, null, null);
try {
if (c.moveToNext()) {
ContentValues values = new ContentValues();
return c.getString(c.getColumnIndex("value"));
} else {
return null;
}
} catch (Exception e) {
WXLogUtils.e("weex_storage", "DefaultWXStorage occurred an exception when execute getItem:" + e.getMessage());
return null;
} finally {
c.close();
}
}
iOS 单聊窗口的昵称显示
原理就是,通过 weex storage 与原生代码数据打通,代码实现参考了 weex sdk storage module 的实现。
实际上就是读取 plist 文件中的数据字典,取出 weex js 存入的用户昵称。
EaseBaseMessageCell.m
- (NSString *)filePathForKey
{
return [[self directory] stringByAppendingPathComponent:@"wxstorage.plist"];
}
- (NSString *)directory {
static NSString *storageDirectory = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
storageDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
storageDirectory = [storageDirectory stringByAppendingPathComponent:@"wxstorage"];
});
return storageDirectory;
}
- (NSString *)getNickname:(NSString *)key
{
NSString *filePath = [self filePathForKey];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
NSString *contents = [dict objectForKey:key];
if (contents) {
return contents;
} else {
return @"";
}
}
- (void)setModel:(id<IMessageModel>)model
{
[super setModel:model];
if (model.avatarURLPath) {
[self.avatarView sd_setImageWithURL:[NSURL URLWithString:model.avatarURLPath] placeholderImage:model.avatarImage];
} else {
self.avatarView.image = model.avatarImage;
}
// JD set nickname
model.nickname = [self getNickname:[NSString stringWithFormat:@"chat_%@", [model.message.from lowercaseString]]];
// end set nickname
...
}
iOS 会话列表的用户昵称
EaseUI/EMUIKit/ViewController/EaseConversationListViewController.m 的函数 tableViewDidFinishTriggerHeader 加入
if (model) {
+ // JD set nickname
+ model.title = [self getNickname:[NSString stringWithFormat:@"chat_%@", [converstion.conversationId lowercaseString]]];
+ // end set nickname
[self.dataArray addObject:model];
}
}
对应的读取 weex storage 的方法需要 copy 单聊里的实现。
环信 user id 的大小写问题
发现一个诡异的问题,服务端注册信鸽聊天账号时,使用的是大写字母,但是信鸽 SDK 读取到的却是全小写。
查了一下才发现,信鸽默认会将账号中的大写字母转换成小写。。。坑爹货,再喊一声,“环信的开发都是傻逼 ”
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式