1.准备工作 : 应用接入指引
注意 sdkappid 和 accounttype ,之后将会在代码中用到。
2.了解用户集成体系:独立模式和托管模式
如果您的APP自主维护用户的注册、用户身份的验证,则应当使用独立模式,
如果您只是想快速开发一个APP原型,云通信可以为您提供一套符合业界通用安全标准的用户体系,用户的注册、用户身份的验证将全部由云通信提供,此时应当选用托管模式。
【独立模式】:用户帐号信息由开发者保存,用户身份验证(比如注册与验密)也由开发者负责;
【托管模式】:由腾讯为开发者提供帐号的密码注册、存储和密码验证,以及第三方 openid 和 token 的托管验证服务。
公私钥(密码学中非对称加密算法中的概念,用于鉴别开发者用户的身份合法性)
【独立模式】:私钥由开发者保存,公钥由腾讯保存。开发者使用私钥生成用户签名 UserSig,腾讯使用公钥对签名 UserSig 进行校验。
【托管模式】:私钥由腾讯保存,公钥由开发者保存。腾讯使用私钥生成用户签名 UserSig,开发者可以使用公钥对签名 UserSig 进行校验,注意,对于第三方开放帐号,此时不需要公私钥。
本测试案例选择的是托管模式,这里由 TLS 为开发者提供 App 帐号的密码注册、存储和密码验证。帐号验证成功后,派发私钥加密生成的签名到客户端,App 业务服务器可以通过 下载的公钥 解密签名进行验证。
3.开始项目
首先下载demo,并按照demo格式将以下四个moudle集成
更改sdk库中的参数
demo中是三个tab,我们测试的例子中只有一个聊天列表的页面。主要为ConversationFragment,这里是为了测试是我们自己的逻辑,不同于demo中的ConversationFragment。
想要实现点对点聊天,如果为了方便 我们可以直接在腾讯云通信后台中配置中手动添加两个管理员
并下载用户凭证,分别得到admin1和admin2的 usersig 用户登录所需的两个参数一个是id,另一个就是UserSig
初始化配置
@Override
public void initTencentImConfig() {
//初始化IMSDK
InitBusiness.start(mView.getApplicationContext(), TIMLogLevel.DEBUG.ordinal());
//初始化TLS
TlsBusiness.init(mView.getApplicationContext());
Log.d("tencentim", "初始化腾讯云Im");
String id = TLSService.getInstance().getLastUserIdentifier();
UserInfo.getInstance().setId(id);
UserInfo.getInstance().setUserSig(TLSService.getInstance().getUserSig(id));
// 初始化TLSSDK
TLSHelper tlsHelper = TLSHelper.getInstance().init(mView.getApplicationContext(), Constant.SDK_APPID);
//登录
login();
//simulateRegistered();//模拟注册
}
3登录
private void login(){
LoginBusiness.loginIm("admin1",
"eJx1z09PgzAYx-E7r6LpVWNoiwxMPLCNsC7imMM-eGmAduYJ0nVQF6fxvRtxiVx8rr9P8s3z6SCEcH6zuSjrevemrbBHozC6QpgxFlJ8-geMASlKK1gnB0A81yWUTggbKfVuoFOi3FrV-arLiR*4PzdSIJW2sIWTKWULmoz2XjZi6P0f6uFlGNP4fsYT6S9YlUyrffC4mpuP43Ma8Wy*uivyPuN6Rj2Z5E8*OVQmgjhqikIHTbrTSQNn1XT-cKhjEoYZvG5aWsiA6wVdrvntMl1fj5IWWnX6iTE-DJhHsfPlfAPflld1",
new TIMCallBack() {
@Override
public void onError(int i, String s) {
Log.d("tencentim", s);
Toast.makeText(mView.getContext(), s, Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess() {
Toast.makeText(mView.getContext(), "admin1登录成功", Toast.LENGTH_SHORT).show();
sendConversation();
}
});
}
发送消息
//通用消息发送
//为了生成对话,每次跳转到这里都发送一条消息给对方
@Override
public void sendConversation() {
TIMConversation timConversation;
//获取单聊会话
String peer = "admin2"; //获取与用户 "xxx" 的会话
timConversation = TIMManager.getInstance().getConversation(
TIMConversationType.C2C, //会话类型:单聊
peer); //会话对方用户帐号//对方id
//构造一条消息
TIMMessage msg = new TIMMessage();
//添加文本内容
TIMTextElem elem = new TIMTextElem();
elem.setText("你好admin2,我是admin1,哈哈哈");
//将elem添加到消息
if (msg.addElement(elem) != 0) {
Log.d("tencentim", "addElement failed");
return;
}
//发送消息
timConversation.sendMessage(msg, new TIMValueCallBack() {//发送消息回调
@Override
public void onError(int code, String desc) {//发送消息失败
//错误码code和错误描述desc,可用于定位请求失败原因
//错误码code含义请参见错误码表
Log.d("tencentim", "send message failed. code: " + code + " errmsg: " + desc);
}
@Override
public void onSuccess(TIMMessage msg) {//发送消息成功
Log.e("tencentim", "SendMsg ok");
}
});
}
取得会话
/**
* 取得会话
*/
@Override
public void getConversation() {
List list = TIMManagerExt.getInstance().getConversationList();
List result = new ArrayList<>();
for (TIMConversation conversation : list) {
//continue用来结束本次循环
if (conversation.getType() == TIMConversationType.System) continue;
result.add(conversation);
TIMConversationExt conversationExt = new TIMConversationExt(conversation);
conversationExt.getMessage(1, null, new TIMValueCallBack>() {
@Override
public void onError(int i, String s) {
Log.e("tencentim", "get message error" + s);
}
@Override
public void onSuccess(List timMessages) {
if (timMessages.size() > 0) {
mView.updateMessage(timMessages.get(0));
}
}
});
}
mView.initView(result);
}
通知view更新列表,将conversations添加到adapter中,更新列表。当然,我们前提会注册监听器
public class ConversationPresenter implements ConversationContract.Presenter, Observer {
private ConversationContract.View mView;
private TLSStrAccRegListener strAccRegListener;
private TLSHelper tlsHelper;
public ConversationPresenter(ConversationContract.View view) {
//注册消息监听
MessageEvent.getInstance().addObserver(this);
//注册刷新监听
RefreshEvent.getInstance().addObserver(this);
//注册好友关系链监听
FriendshipEvent.getInstance().addObserver(this);
//注册群关系监听
GroupEvent.getInstance().addObserver(this);
this.mView = view;
mView.setPresenter(this);
}
......
......
@Override
public void update(Observable observable, Object data) {
if (observable instanceof MessageEvent) {
Log.d("tencentim", "更新消息");
if (data instanceof TIMMessage) {
TIMMessage msg = (TIMMessage) data;
mView.updateMessage(msg);
}
} else if (observable instanceof FriendshipEvent) {
Log.d("tencentim", "更新好友链");
FriendshipEvent.NotifyCmd cmd = (FriendshipEvent.NotifyCmd) data;
switch (cmd.type) {
case ADD_REQ:
case READ_MSG:
case ADD:
mView.updateFriendshipMessage();
break;
}
} else if (observable instanceof GroupEvent) {
Log.d("tencentim", "更新群组");
GroupEvent.NotifyCmd cmd = (GroupEvent.NotifyCmd) data;
switch (cmd.type) {
case UPDATE:
case ADD:
mView.updateGroupInfo((TIMGroupCacheInfo) cmd.data);
break;
case DEL:
mView.removeConversation((String) cmd.data);
break;
}
} else if (observable instanceof RefreshEvent) {
Log.d("tencentim", "更新会话列表");
getConversation();
mView.refresh();
}
}
}
更改登录 admin1 admin2 的信息(id,和usersig) 分别运行,效果如下图
登录admin1 模拟发消息给admin2
再登录admin2 模拟发消息给admin1 同时他也收到admin1之前给admin2发的消息
如此以来 通过手动添加实现一个简单的c2c聊天
但是我们不能都通过后台添加管理员 我们需要注册登录实现聊天,那我们开始通过代码实现。首先我们要模拟注册和模拟登录,托管模式我们主要依靠的是tls。主要写模拟注册和模拟登录 省略页面部分。
主要流程 simulateRegistered();//模拟注册--->simulateLogin();//模拟登录,主要是为了获得usersig-->客户端登录验证-->发送消息
private void simulateRegistered() {
// 引导用户输入合法的用户名和密码
int result = tlsHelper.TLSStrAccReg("用户1", "12345678", new TLSStrAccRegListener() {
@Override
public void OnStrAccRegSuccess(TLSUserInfo tlsUserInfo) {
/* 成功注册了一个字符串帐号, 可以引导用户使用刚注册的用户名和密码登录 */
simulateLogin("用户1","12345678");
}
@Override
public void OnStrAccRegFail(TLSErrInfo tlsErrInfo) {
/* 注册失败,请提示用户失败原因 */
}
@Override
public void OnStrAccRegTimeout(TLSErrInfo tlsErrInfo) {
/* 网络超时,可能是用户网络环境不稳定,一般让用户重试即可。*/
}
});
if (result == TLSErrInfo.INPUT_INVALID){
Log.d("tencentim","注册失败");
}
}
private void simulateLogin(final String username, String password) {
tlsHelper.TLSPwdLogin(username, password.getBytes(), new TLSPwdLoginListener() {
@Override
public void OnPwdLoginSuccess(TLSUserInfo tlsUserInfo) {
String usersig = tlsHelper.getUserSig(tlsUserInfo.identifier);
Log.d("tencentim","usersig:"+usersig);
//获得usersig后登录
LoginBusiness.loginIm(username, usersig,
new TIMCallBack() {
@Override
public void onError(int i, String s) {
Log.d("tencentim", s);
Toast.makeText(mView.getContext(), s, Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess() {
Toast.makeText(mView.getContext(), username + "登录成功", Toast.LENGTH_SHORT).show();
sendConversation();
getConversation();
}
});
}
@Override
public void OnPwdLoginReaskImgcodeSuccess(byte[] bytes) {
}
@Override
public void OnPwdLoginNeedImgcode(byte[] bytes, TLSErrInfo tlsErrInfo) {
Log.d("tencentim","用户需要进行图片验证码的验证");
}
@Override
public void OnPwdLoginFail(TLSErrInfo tlsErrInfo) {
}
@Override
public void OnPwdLoginTimeout(TLSErrInfo tlsErrInfo) {
}
});
}