环信即时通讯集成过程

最近一直挺忙,使用了一些第三方的东西,也遇见了不少的问题,前面使用的一些还好,比如推送,分享这些第三方都比较容易集成,这次集成环信的即时通讯还是费了一些周折,刚弄完,赶紧记录一下。

一.前期需要注意的地方

总的来说环信的开发文档和SDK做的已经很简单了,但是毕竟是第一次集成,使用别人的东西难免有点摸不着头。这次使用环信3.0版本来集成。基本上前面的操作都可以按着文档的说明进行了,这里感觉添加sdk前需要注意几个地方。

1.先对文档进行一个全面的阅读

我刚开始在做其他的第三方集成时也很着急,想着怎么赶紧找到一个入口。最后发现着急没用,所以先阅读以下文档,知道自己需要的功能大体怎么处理,需要集成哪一些jar包等。这次我开始就没有注意,阅读文档时就把独立的sdk的jar和so包都复制到了项目中,最后发现,有一个更好用一些的东西EaseUI 这个module,直接导入这个module就可以不用再去添加各种jar和so文件了。所以,我们有一个整体的把握很重要。

2.了解easeUI包

easeUI这个包下包含了好些jar还有百度地图的包,在【Android SDK 介绍和导入】这个地方说明的包基本都是这里的。

环信即时通讯集成过程_第1张图片

了解这些方便我们处理后边的冲突等问题。比如我的项目之前放入了百度sdk的jar,这里也有,但是版本不同可能引发问题,也可能由于重复引入jar导致问题。

二.添加集成

1.集成easeUI

我使用了easeUI这个module直接集成的,这样我们可以使用环信提供的一些UI,比如EaseChatFragment ,这是一个聊天界面,一般来说自己处理这个页面还是有一些困难或者问题。集成出现的问题。

环信即时通讯集成过程_第2张图片

这个也是官方提出的,首先我们要处理这个,我觉得还是把这个module的v4包版本号增加大这个方式好一些,例如使用:把 v4 包的版本号加大,譬如 compile 'com.android.support:support-v4:23.2.1这样编译就可以了。下面就是按照文档找到自己需要的API集成了。从注册,到登录,然后获取好友列等操作

2.API集成出现的问题

1).一些异常比如出现:unknow server exception(异常信息没有截图),这个问题其实是我们没有按照文档说明去做,

//群主加人调用此方法

EMClient.getInstance().groupManager().addUsersToGroup(groupId, newmembers);//需异步处理

上面接口说了使用异步处理,我没有使用异步也就出现了异常。

2).

3.使用easeUI

我们在环信注册了用户之后就会有一个环信的id,通过这个id我们就可以和对方进行简答的通信了。使用EaseChatFragment。

按照文档说明创建一个Activity,然后写一下的代码:

EaseChatFragment chatFragment = new EaseChatFragment();

        Bundle args = new Bundle();

        args.putInt(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_SINGLE);

        args.putString(EaseConstant.EXTRA_USER_ID, getIntent().getStringExtra("userID"));

        chatFragment.setArguments(args);

        FragmentManager supportFragmentManager = getSupportFragmentManager();

        getSupportFragmentManager().beginTransaction().add(R.id.container, chatFragment).commit();

//container是你创建的activity的根布局的id


 /**

     * 发起聊天 这个是从MainActivty或者其他页面发起聊天,传入一个你注册的环信id

     * @param input

     */

    private void startChat(String input) {

        //new出EaseChatFragment或其子类的实例

        if(!TextUtils.isEmpty(input)){

            Intent intent = new Intent(MainActivity.this, ChatActivity.class);

            intent.putExtra("userID",input);

            startActivity(intent);

        }else{

            Toast.makeText(this, "请输入一个用户id", Toast.LENGTH_SHORT).show();

        }

    }

完成上述的注册,登录和EaseChatFragment后通信功能基本上就可以实现了。如图:

环信即时通讯集成过程_第3张图片

到此环信的集成主要功能也就是完成的,其他的可能会用到聊天列表,通讯录这些按照文档集成就可以,不过环信不对通讯录进行维护,也就是说要是保存用户信息什么的东西,需要我们自己的服务器来保存,然后在使用时根据环信id去服务器获取这个用户的其他信息。

4.修改用户头像和用户名

上面的那个图我们看到了用户头像是默认的没有图片,这个怎么处理?环信只是给出了一个思路,demo中有实现的逻辑,但是找出来还是不太容易。

环信给出的两个方案:

1).从app服务器获取用户数据头像

2).从消息扩展中获取用户数据

最后我选了第二重方案,我也不知道怎么就选了第二种方法,刚开始对这个问题很晕,没有一点思路,在网上找了几个相关的,所以两个方法弄的有点晕,然后就没办法,按照一个方式尝试,最后逐渐明白,其实这个方式相对来听容易实现,就是要知道从什么地方下手。看看最后结果如图:

环信即时通讯集成过程_第4张图片

图片中已经有了头像了。

我们在使用集成的过程中可能需要对EaseChatFragment进行一个重写,就像上图图右上角是一个垃圾桶图标,我们自己需要一个点击进入用户信息的页面,所以从写这个EaseChatFragment的一个方法:

 @Override

    protected void setUpView() {

        super.setUpView();

        //messageList.init(toChatUsername, chatType, new CustomChatRowProvider());//messageList初始化??

        titleBar.setRightImageResource(R.mipmap.user);

        titleBar.getRightLayout().setOnClickListener(new View.OnClickListener() {//处理点击

            @Override

            public void onClick(View v) {

                if (chatType == EaseConstant.CHATTYPE_GROUP ) {//群聊,传递当前的 emGroup

                    Intent intent = new Intent(getActivity(), IMDiscussInfoActivity.class);//群组,需要一个id

                    intent.putExtra("conversationID", toChatUsername);

                    startActivity(intent);

                } else{// 单聊EaseConstant.CHATTYPE_SINGLE

                    Intent intent = new Intent(getActivity(), IMPersonalInfoActivity.class);//个人

                    intent.putExtra("conversationID", toChatUsername);//回话id就是手机号码

                    startActivity(intent);

                }

            }

        });

    }

我们在 EaseChatFragment找上述方法重写的过程可能会发现有一个接口:EaseChatFragmentHelper,如果你有了这个印象后边可能就容易了,网上的其他资料让你能快速想起来然后处理他。这个接口就是文档说的发送扩扩展消息要使用的,所以按照文档说明从写接口的方法:

 /**

     * 实现EaseChatFragmentHelper接口方法

     * 希望通过设置附加消息实现头像传递

     * @param message

     */

    @Override

    public void onSetMessageAttributes(EMMessage message) {

        //发送消息时附加参数p

        LogUtils.e("TAG","onSetMessageAttributes");

        Preferences preferences = new Preferences(getActivity());

        message.setAttribute(ConstantValue.IM_USER_ID, preferences.getUserPhoneNumber());//标识用户的手机号

        message.setAttribute(ConstantValue.IM_NICK_NAME, preferences.getUserName());

        message.setAttribute(ConstantValue.IM_USER_IMAGE, preferences.getString("userImage")) ;

        //这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

        LogUtils.e("TAG","fasong用户头像:"+preferences.getString("userImage"));

    }


写完不要忘记了在你的这个Fragment中在重写一个方法比如:onCreate().因为我们要注册这个接口的实现。

@Override

    public void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setChatFragmentListener(this);//注册接口,EaseChatFragment提供的方法

    }

这样看,基本上完成了扩展消息的发送。接下来就是消息的接收和保存了。

在最初阅读文档按照步骤做的时候有没有注意到demo的Application中注册了这样一句:

 //init demo helper

 DemoHelper.getInstance().init(applicationContext);

文档说我们要这样注册:

EMOptions options = new EMOptions();

// 默认添加好友时,是不需要验证的,改成需要验证

options.setAcceptInvitationAlways(false);

...

//初始化

EMClient.getInstance().init(applicationContext, options);

//在做打包混淆时,关闭debug模式,避免消耗不必要的资源

EMClient.getInstance().setDebugMode(true);

这就导致了我当初没有看清楚demo中的那句话。现在我们点击进去看看:

/**
 * init helper
 * @param context application context
 */
public void init(Context context) {
    demoModel = new DemoModel(context);
    EMOptions options = initChatOptions();
    //use default options if options is null
   if (EaseUI.getInstance().init(context, options)) {
       appContext = context;
       //debug mode, you'd better set it to false, if you want release your App officially.
       EMClient.getInstance().setDebugMode(true);
       //get easeui instance
       easeUI = EaseUI.getInstance();
       //to set user's profile and avatar
       setEaseUIProviders();
      //initialize preference manager
      PreferenceManager.init(context);
      //initialize profile manager
      getUserProfileManager().init(context);

      // TODO: set Call options 此处省略中间若干刚...
       
       setGlobalListeners();
      //broadcastManager = LocalBroadcastManager.getInstance(appContext);
       // initDbDao();
   }
}

这里完成了我们的注册和其他的操作。

这里我们需要知道的就是除了EaseUI注册的那几行之外的代码:

setEaseUIProviders();

setGlobalListeners();

下面是我修改后的项目中的代码:

 *

     * @param context application context

     */

    public void init(Context context) {

        //demoModel = new DemoModel(context);

        EMOptions options = new EMOptions();

        options.setAcceptInvitationAlways(false);//添加好友不需要验证

        //use default options if options is null

        if (EaseUI.getInstance().init(context, options)) {

            appContext = context;

            //debug mode, you'd better set it to false, if you want release your App officially.

            EMClient.getInstance().setDebugMode(true);

            //get easeui instance

            easeUI = EaseUI.getInstance();

            //to set user's profile and avatar

            preferences = new Preferences(context);

            setEaseUIProviders();

        }

    }


对比发现除了注册的之外关键的就是

setEaseUIProviders();这句话

你可以自己在demo中看看这,其实最主要的就是他。进入这个方法发现有一段代码:

easeUI.setUserProfileProvider(new EaseUserProfileProvider() {
    
    @Override
    public EaseUser getUser(String username) {
        return getUserInfo(username);
    }
});
突然明白了 getUserInfo(username)就是返回最后用户消息的那个方法,他返回一个EaseUser对象。我重写后的getUserInfo(username)如下:

private EaseUser getUserInfo(String username) {

        EaseUser user = null;

        if (username.equals(EMClient.getInstance().getCurrentUser())) {

            //如果用户是本人,就设置自己的头像

            user = new EaseUser(username);

            user.setAvatar(preferences.getString(ConstantValue.USER_IMAGE));

            user.setNick(preferences.getUserName());

            return user;

        }else if(!username.equals(EMClient.getInstance().getCurrentUser())){

            DbManager dbManager = x.getDb(MainApplication.getInstance().initDB());

            try {

                IMContract imContract = dbManager.findById(IMContract.class, username);

                if(imContract!=null){

                    LogUtils.e(TAG,"数据库查询结果:"+imContract.getContraactPhone());

                    user = new EaseUser(username);

                    user.setAvatar(imContract.getImageUrl());

                    user.setNick(imContract.getNickName());

                    return user;

                }

            } catch (DbException e) {

                e.printStackTrace();

            }

        }

这个方法给EaseUser对象赋值了。这里还有一点没有说明。前面在

EaseChatFragmentHelper 接口中添加了扩展消息,我们还没有取出来呢。

现在看看环信demo中和我写的不一样的地方:就是有一个

setGlobalListeners();

这个方法,这个就是环信接收消息的地方。当时点击进去发现一大片。我们在这个方法的最后发现了这么一句:

registerMessageListener();

这才是真正接收消息的地方。在回忆一下当初看文档的时候,在消息这个模块中有这个借口:

EMClient.getInstance().chatManager().addMessageListener(msgListener);

EMMessageListener msgListener = new EMMessageListener(){...}

现在需要做的就是在这里实现接口方法,我研究后重写的:

@Override

        public void onMessageReceived(List list) {

            LogUtils.e(TAG, "onMessageReceived执行消息监听..");

            receivedListener.onMessageReceived(list);

            for (EMMessage message : list) {//保存下数据

                String chatUserId = message.getStringAttribute(ConstantValue.IM_USER_ID, "");

                String avatarUrl = message.getStringAttribute(ConstantValue.IM_USER_IMAGE, "");

                String nickName = message.getStringAttribute(ConstantValue.IM_NICK_NAME, "");

                LogUtils.e("TAG", "appjieshou消息获取的数据是chatUserId:" + chatUserId);

                DbManager db = x.getDb(initDB());

                IMContract imContract = new IMContract();

                imContract.setContraactPhone(chatUserId);

                imContract.setImageUrl(avatarUrl);

                imContract.setNickName(nickName);

                try {

                    db.saveOrUpdate(imContract);

                } catch (DbException e) {

                    e.printStackTrace();

                    LogUtils.e(TAG,"数据库操作异常:"+e.getMessage());

                }

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

            }

        }

这里获取当初发送的消息并保存在数据库中,就好了,我们在使用的时候根据环信的id去查数据库就可以拿到用户信息了。这里我使用的是xUtils3中的数据库操作。

ChatHelper.getInstance().getNotifier().onNewMsg(message);//ChatHelper就是demo中的DemoHelper这个是接收到消息后发送一个通知的.

现在回到前面的getUserInfo(username)方法中,可以看到这里只是根据username进行了数据库查询,然后返回一个EsaseUser对象。这样我们就完成了用户头像和其他信息的传递。在一次聊天就会发现有头像和用户名信息了。

这里需要注意,头像这里直接传递一个图片的url就好了,环信已经封装好了对他的处理。

如果你在研究的过程发现了EaseUserUtils这个你就知道了:

/**
 * set user avatar
 * @param username
 */
public static void setUserAvatar(Context context, String username, ImageView imageView){
    Log.e("TAG","setUserAvatar设置头像返回:"+username);
   EaseUser user = getUserInfo(username);
    if(user != null && user.getAvatar() != null){
        try {
            int avatarResId = Integer.parseInt(user.getAvatar());
            Glide.with(context).load(avatarResId).into(imageView);
        } catch (Exception e) {
            //use default avatar
            Glide.with(context).load(user.getAvatar()).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.ease_default_avatar).into(imageView);
        }
    }else{
        Glide.with(context).load(R.drawable.ease_default_avatar).into(imageView);
    }
}

可以看到在这里使用了Glide来加载图片,没有图片的url时使用本地的这个替代。



参考资料:

1. .http://www.cnblogs.com/zhang-cb/p/6292254.html

2.http://www.imgeek.org/article/825307856




你可能感兴趣的:(第三方集成)