Android 融云即时通讯开发

项目中需要用到即时通讯,经过一番研究,现两个用户已可以互相通信;下面介绍关于融云的开发过程:

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)登录融云。

扫描二维码关注公众号,回复: 3853795 查看本文章
    /**
     * <p>连接服务器,在整个应用程序全局,只需要调用一次,需在 { init(Context)} 之后调用。</p>
     * <p>如果调用此接口遇到连接失败,SDK 会自动启动重连机制进行最多10次重连,分别是1, 2, 4, 8, 16, 32, 64, 128, 256, 512秒后。
     * 在这之后如果仍没有连接成功,还会在当检测到设备网络状态变化时再次进行重连。</p>
     *
     * @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<String, String>();
                    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().setMessageAttachedUserInfo(true);该行代码,表示在发送消息时携带用户信息(头像,昵称)即在会话界面,可实时刷新显示用户的头像

昵称信息;需在会话界面添加RongIM.getInstance().setCurrentUserInfo(new UserInfo(myId, myName, Uri.parse(myHeadUrl))); 方可使用;myId为当前用户Id,myName为当前用户昵称,myHeadUrl为当前用户头像地址。

b.融云提供会话列表界面 ConversationListFragment,因此只需新建Activity加载Fragment,在项目清单文件中,需要对其配置,配置如下,

android:host 填写项目包名
  <activity
            android:name=".ui.message.MessageActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="com.meidukang.clienthelper"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

MessageActivity,为加载ConversationListFragment的Activity,需再其布局文件中加入:

 <fragment
        android:id="@+id/conversationlist"
        android:name="io.rong.imkit.fragment.ConversationListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

在MessageActivity中,需代码配合使用:
 /**
     * 加载会话页面 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);
    }

c.融云提供会话界面,ConversationFragment,其加载同加载会话列表界面相同,新建ConversationActivity,清单文件配置如下:

  <activity
            android:name=".ui.message.ConversationActivity"
            android:launchMode="singleTop"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="com.meidukang.clienthelper"
                    android:pathPrefix="/conversation/"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

布局文件加入如下代码:
  <fragment
        android:id="@+id/conversation"
        android:name="io.rong.imkit.fragment.ConversationFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
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);
    }

其中mTargetId(对方的Id),mTitleName(可自定义,显示在聊天界面标题栏上的文字如“与xxx聊天”)为启动会话界面时传入的值(稍后介绍如何开启会话),获取方式不可更改;mConversationType为会话类型,如单聊,群组、聊天室、客服等不同会话类型。不同会话类型启动方式类似(此处只介绍单聊与客服的实现)。

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因受到上传文件大小的限制,无法上传,如有需要可在下方留下邮箱

猜你喜欢

转载自blog.csdn.net/androidforwell/article/details/72963228