1.融云的业务架构
可在http://www.rongcloud.cn/docs/quick_start.html,中查看融云的架构介绍,简单来说,产品的用户信息(如头像、昵称、id等)存储在自己的服务器中,用户的通信消息则通过融云转发,若想获取 聊天记录,可通过付费获取,具体价格及服务见http://www.rongcloud.cn/docs/payment.html
2.会话的实现
会话的实现,可根据自己的业务需求选择添加功能,最基本的功能有可文字、语音聊天,发送图片,文件;可添加的服务见下表(若想添加服务需要在项目中导入相应module);
若使用最基础的服务,只需导入IMKit及IMLib包,即可;其中IMKit可提供会话及会话列表界面,无需自己开发,只需提供Activity加载融云的相关fragment即可(后续介绍);若需自己独立定制UI界面,则可使用IMLib提供的接口,获取发来的消息内容、消息数及用户等信息,从而显示在自己的UI界面上。
在此,只介绍如何使用基础的会话服务,其他服务同此类似,具体如何操作详见:http://www.rongcloud.cn/docs/android.html
以下为对该部分内容的概述:
a.需到融云平台注册登录,申请Appkey,若两个app互相通信则需用相同的Appkey;融云针对调试版与正式版app分为开发环境与调试环境,具有不同的Appkey,若产品上线,则需在融云平台申请上线并获取新的Appkey.如下图:
b.融云为每一个用户生成唯一的token值。用于登录融云平台服务(不通过自己的服务器),若不通过token登陆到融云则不可使用聊天服务,调用以下代码登录融云,若登录成功则会回调onSuccess(String userid)方法,此时可处理自己登录成功后的逻辑;若调用失败则调用onError(RongIMClient.ErrorCode errorCode)方法,可根据返回的errorCode 查询相应的错误信息;若token失效,则会回调onTokenIncorrect()方法,此时需重新申请新的token,再次调用connect(String token)重新登录融云;将申请的融云token存储在本地,而后每次打开app时均需要使用token,调用connect(String token)登录融云。
/**
* 连接服务器,在整个应用程序全局,只需要调用一次,需在 { init(Context)} 之后调用。
* 如果调用此接口遇到连接失败,SDK 会自动启动重连机制进行最多10次重连,分别是1, 2, 4, 8, 16, 32, 64, 128, 256, 512秒后。
* 在这之后如果仍没有连接成功,还会在当检测到设备网络状态变化时再次进行重连。
*
* @param token 从服务端获取的用户身份令牌(Token)。
* @return RongIM 客户端核心类的实例。
*/
private void connect(String token) {
Log.i(TAG,"connect");
if (getApplicationInfo().packageName.equals(Utils.getCurProcessName(getApplicationContext()))) {
RongIM.connect(token, new RongIMClient.ConnectCallback() {
/**
* Token 错误。可以从下面两点检查 1. Token 是否过期,如果过期您需要向 App Server 重新请求一个新的 Token
* 2. token 对应的 appKey 和工程里设置的 appKey 是否一致
*/
@Override
public void onTokenIncorrect() {
Log.i(TAG, "--onTokenIncorrect");
paramsMap=new HashMap();
paramsMap.put("nickName",(String) Utils.getShare(LoginActivity.this,ConfigUrl.USER_NICK_NAME,"用户昵称"));
paramsMap.put("userId",(String) Utils.getShare(LoginActivity.this,ConfigUrl.USER_ID,"用户id"));
paramsMap.put("userType","CM");
httpUtilHelper.doCommandHttp(paramsMap,ConfigUrl.GET_TOKEN_URL,TOKEN_CODE);
}
/**
* 连接融云成功
* @param userid 当前 token 对应的用户 id
*/
@Override
public void onSuccess(String userid) {
Log.i(TAG, "--onSuccess" + userid);
if (loadingDialog.isShowing()){
loadingDialog.dismiss();
}
Utils.saveShare(LoginActivity.this,ConfigUrl.LOGIN,true);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
//finish();
}
/**
* 连接融云失败
* @param errorCode 错误码,可到官网 查看错误码对应的注释
*/
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
Log.i(TAG, "--onError" + errorCode);
}
});
}
}
若写测试Demo时需两个用户互相通讯,则可在融云平台申请token值(此时无需通过自己的后台服务器申请),可在 API调试 中生成新的用户,如下图所示,userId,name,portraitUri均可自己定义。
正式开发时,需通过自己的服务器申请融云token,由自己的服务服务器返回融云的token,用户id等用户信息。在以后的聊天中,通过用户id找到用户,方可通信。
c.下载IMKit及IMLib包并将其作为module导入项目中,注意配置;在项目清单文件(AndroidManifest.xml)及IMLib 项目清单文件(AndroidManifest.xml)配置AppKey。
3.即时通讯的代码设置:
a.在Application中初始化,代码如下:
RongIM.init(this);
RongIM.getInstance().setMessageAttachedUserInfo(true);
initRongIMCLient();
private void initRongIMCLient(){
/**
* OnCreate 会被多个进程重入,这段保护代码,确保只有您需要使用 RongIMClient 的进程和 Push 进程执行了 init。
* io.rong.push 为融云 push 进程名称,不可修改。
*/
if (getApplicationInfo().packageName.equals(Utils.getCurProcessName(this)) ||
"io.rong.push".equals((Utils.getCurProcessName(this)))){
RongIMClient.init(this);
}
}
昵称信息;需在会话界面添加RongIM.getInstance().setCurrentUserInfo(new UserInfo(myId, myName, Uri.parse(myHeadUrl))); 方可使用;myId为当前用户Id,myName为当前用户昵称,myHeadUrl为当前用户头像地址。
b.融云提供会话列表界面 ConversationListFragment,因此只需新建Activity加载Fragment,在项目清单文件中,需要对其配置,配置如下,
android:host 填写项目包名
MessageActivity,为加载ConversationListFragment的Activity,需再其布局文件中加入:
/**
* 加载会话页面 ConversationListFragment
*/
private void enterFragment() {
ConversationListFragment fragment = (ConversationListFragment) getSupportFragmentManager().findFragmentById(R.id.conversationlist);
Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()
.appendPath("conversationlist")
.appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")
.build();
fragment.setUri(uri);
}
在ConversationActivity中,需代码配合使用:
private Conversation.ConversationType mConversationType;//会话类型
private Intent intent;
private void initDatas(){
intent=getIntent();
mTargetId=intent.getData().getQueryParameter("targetId");
mTitleName=intent.getData().getQueryParameter("title");
myId=(String) Utils.getShare(this,ConfigUrl.USER_ID,"用户id");
myName=(String) Utils.getShare(this,ConfigUrl.USER_NICK_NAME,"用户昵称");
myHeadUrl=(String) Utils.getShare(this,ConfigUrl.HEAD_URL,"头像");
mConversationType = Conversation.ConversationType.valueOf(intent.getData().getLastPathSegment().
toUpperCase(Locale.getDefault()));
enterFragment(mConversationType,mTargetId);
tv_title_name.setText(mTitleName);
RongIM.getInstance().setCurrentUserInfo(new UserInfo(myId, myName, Uri.parse(myHeadUrl)));
}
/**
* 加载会话页面 ConversationFragment
*
* @param mConversationType
* @param mTargetId
*/
private void enterFragment(Conversation.ConversationType mConversationType, String mTargetId) {
ConversationFragment fragment = (ConversationFragment) getSupportFragmentManager().findFragmentById(R.id.conversation);
Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()
.appendPath("conversation").appendPath(mConversationType.getName().toLowerCase())
.appendQueryParameter("targetId", mTargetId).build();
fragment.setUri(uri);
}
d.开启单聊:
if (RongIM.getInstance()!=null&& !TextUtils.isEmpty(nickName)){
RongIM.getInstance().startPrivateChat(this,userId,nickName);
}
如此即可开启单聊。startPrivateChat()表示会话界面的 mConversationType值为单聊模式,userId对应mTargetId,nickName对应mTitleName。
e.开启客服,客服同样分为开发板与生产版,需申请开通服务
//首先需要构造使用客服者的用户信息
private CSCustomServiceInfo.Builder csBuilder;
private CSCustomServiceInfo csInfo;
csBuilder=new CSCustomServiceInfo.Builder();
csInfo=csBuilder.nickName("客服昵称").build();
if (RongIM.getInstance()!=null){
RongIM.getInstance().startCustomerServiceChat(this, "客服Id","在线客服",csInfo);
}
如此即可进入客服聊天,点击”进入客服后台“即可与用户聊天。
Demo因受到上传文件大小的限制,无法上传,如有需要可在下方留下邮箱