基于融云(RongCloud)的IM
1、准备工作
注册开发者账号
SDK的下载,融云SDK以插件的形式独立提供,根据自己的需求单独或者组合下载其中
IMKit是集成了会话界面,并且提供个了很多的自定义功能(可有可无,入门推荐)
IMLib提供了基础的通信功能,较轻量,需要自己实现UI和大部分业务逻辑(基础功能必须有)
CallKit、CallLib、Location(基于高德)、PushLib、RedPacket……各部分功能
创建应用,获得APP Key / Secret 这是SDK连接融云服务器的唯一标示,每个APP对应一套
2、导入依赖模块
Android SDK Build-tools >= 27; JDK >=1.7; Android Support V4及其以上版本
因为融云提供SDK的依赖是以库依赖的形式提供,所以需要通过import module进行依赖天剑(PS:注意就是需要先导入IMLib作为基础,不然后面导入其他的模块的时候会报错说没有基础模块)
导入后IM所需应用的权限已经自动在IMLib的AndroidManifest.xml文件中配置好了。
每一个库类似于一个小工程,有自己的build:gradle和AndroidManifest.xml配置文件.对自己模块部分进行设置。
各部分导入之后在进行关联将各模块的build:gradle与主程序的build:gradle进行关联。
- 在主程序的build:gradle的dependence闭包中添加各模块对应的依赖
添加库依赖之后合并编译的时候可能会遇到AndroidManifest.xml部分报错,是因为第三方的依赖和默认APP中的某些标签节点出现重复
解决方法:
修改冲突的属性节点;
tools:place
表明合并时移除低优先级 Library 中的相关属性,使用高优先级 app module 中定义的对应属性内容(需要声明命名空间)常用的Android Studio项目有三种依赖方式:
本地依赖:对本地的jar包(或目录文件)添加依赖
库依赖:对项目中库模块添加依赖关系
远程依赖:对jcenter库上的开源库添加依赖,对于远程依赖,Gradle在构建项目的时候会先检查本地是否已经有这个库的缓存,没有会自动联网下载,然后添加到项目的构建之中。
在Android Studio3.0之后部分compile已经变成了implementation和api:
- 其中api和compile完全一样,没有区别
- 使用implementation的特点:这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。(eg.比如我在一个libiary中使用implementation依赖了gson库,然后我的主项目依赖了libiary,那么,我的主项目就无法访问gson库中的方法。这样的好处是编译速度会加快,推荐首先使用implementation的方式去依赖。)
- testImplementation:是用于声明测试用例库
3、SDK
3.1 SDK的初始化
- 在整个应用程序全局,只需要调用一次 init方法进行初始化。需在主线程中进行。
- 建议在MyApplication类onCreat()方法中进行初始化。每个程序运行时系统会创建一个Application类的对象且只创建一个,并在其中进行某些初始化操作。这个Application的对象的声明周期跟程序的生命周期一致。
3.2 获取Token
-
token机制:token的意思是“令牌”,是用户身份的验证方式,基于token的身份验证:
- 1、客户端使用用户名跟密码请求登录
- 2、服务端收到请求,去验证用户名与密码
- 3、验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
- 4、客户端收到 Token 以后可以把它存储在本地
- 5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
- 6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
-
客户端通过融云 SDK 每次连接服务器时,都需要向服务器提供 Token,以便验证身份。
-
后续登录过程中,就不必再向融云请求 Token,由 App Server 直接提供之前保存过的 Token
-
在客户端获取token
- URL:http://api.cn.ronghub.com/user/getToken.[format]
- [format]表示返回格式,可以是json或者XML(不带中括号)
- HTTP方法:POST
- 表单参数:
- userId-String
- name-String
- portraitUri-String
-
返回的json数据,获取token之后进行本地存储
{"code":200, "userId":"jlk456j5", "token":"sfd9823ihufi"}
-
获取token之后连接服务器,连接服务器,在整个应用程序全局,只需要调用一次。
private void connect(String token) { if(getApplicationInfo().packageName.equals(App.getCurProcessName(getApplicationContext()))) { RongIM.connect(token, new RongIMClient.ConnectCallback() { /** * token出错 */ @Override public void onTokenIncorrect() { } /** * 连接融云成功 */ @Override public void onSuccess(String userid) { Log.d("LoginActivity", "--onSuccess" + userid); //进行本地存储 startActivity(new Intent(LoginActivity.this,MainActivity.class)); finish(); } /** * 连接融云失败 */ @Override public void onError(RongIMClient.ErrorCode errorCode) { } }); } }
3.3设置监听
3.3.1接受消息监听
-
接收消息的监听器,在 init() 之后才能设置。注意,建议设置在 Application 里面,这样才能在整个应用的生命周期,都能监听到接收消息事件。
-
1、创建监听器实现RongIMClient.OnReceiveMessageListener接口,重写onReceived()方法,所有接收到的消息、通知、状态都经由这个监听器处理。包括私聊消息、讨论组消息、群组消息、聊天室消息以及各种状态。
private class MyReceiveMessageListener implements RongIMClient.OnReceiveMessageListener { /** * 收到消息的处理。 * * @param message 收到的消息实体。 * @param left 剩余未拉取消息数目。 * @return 收到消息是否处理完成,true 表示自己处理铃声和后台通知,false 走融云默认处理方式。 */ @Override public boolean onReceived(Message message, int left) { //开发者根据自己需求自行处理 return false; } }
-
2、在Application中注册监听
public static void setOnReceiveMessageListener(RongIMClient.OnReceiveMessageListener listener)
-
3.3.2 设置会话列表界面操作的监听器
-
会话列表操作监听,同上,在调用
init
之后即可进行设置。-
1、创建监听器实现RongIMClient.OnReceiveMessageListener接口,重写onConversationPortraitClick()、onConversationPortraitLongClick()、onConversationLongClick()、onConversationClick()四个方法,分别对应消息里边中每一个子项的头像点击、头像长按、子项长按、子项点击事件。
private class MyConversationListBehaviorListener implements RongIM.ConversationListBehaviorListener{ /** * 当点击会话头像后执行。 * * @param context 上下文。 * @param conversationType 会话类型。 * @param targetId 被点击的用户id。 * @return 如果用户自己处理了点击后的逻辑处理,则返回 true,否则返回 false,false 走融云默认处理方式。 */ boolean onConversationPortraitClick(Context context, Conversation.ConversationType conversationType, String targetId){ } /** * 当长按会话头像后执行。 * * @param context 上下文。 * @param conversationType 会话类型。 * @param targetId 被点击的用户id。 * @return 如果用户自己处理了点击后的逻辑处理,则返回 true,否则返回 false,false 走融云默认处理方式。 */ boolean onConversationPortraitLongClick(Context context, Conversation.ConversationType conversationType, String targetId){ return false; } /** * 长按会话列表中的 item 时执行。 * * @param context 上下文。 * @param view 触发点击的 View。 * @param uiConversation 长按时的会话条目。 * @return 如果用户自己处理了长按会话后的逻辑处理,则返回 true, 否则返回 false,false 走融云默认处理方式。 */ @Override public boolean onConversationLongClick(Context context, View view, UIConversation uiConversation) { return false; } /** * 点击会话列表中的 item 时执行。 * * @param context 上下文。 * @param view 触发点击的 View。 * @param uiConversation 会话条目。 * @return 如果用户自己处理了点击会话后的逻辑处理,则返回 true, 否则返回 false,false 走融云默认处理方式。 */ @Override public boolean onConversationClick(Context context, View view, UIConversation uiConversation) { return false; } }
-
2、在Application中注册监听
RongIM.setConversationListBehaviorListener(new MyConversationListBehaviorListener());
-
3.4 配置会话列表界面(会话适用)
-
融云 IMKit SDK 是使用了 Fragment 作为会话列表和会话界面的组件。 需要建立相应的 Activity ,以静态方式加载融云 Fragment(包括消息列表,聊天界面……)
-
布局文件的设置,注意android:name 固定为"io.rong.imkit.fragment.ConversationListFragment"
(会话为"io.rong.imkit.fragment.ConversationFragment")
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/conversationlist" android:name="io.rong.imkit.fragment.ConversationListFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
-
融云 SDK 是通过隐式调用的方式来实现界面跳转。因此需要在 AndroidManifest.xml 中,会话列表 Activity下面配置intent-filter,其中,android:host 是您应用的包名,需要手动修改,其他请保持不变。
<!-- 会话列表 --> <activity android:name=".ConversationListActivity" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="com.newthread.rongyun" android:pathPrefix="/conversationlist" <!--"/conversation/"--> android:scheme="rong" /> </intent-filter> </activity>