Android SDK 2.8.0 版本升级文档

Android SDK 2.8.0 版本概述

1. 封装了输入栏、表情 tab 页、“+”号区域插件,内置了相册选择器、emoji 表情、地理位置功能。
2. 开放了扩展栏自定义接口,开发者可以移除内置的功能,也可以此基础上添加新的功能,比如添加 gif 表情 tab 页,颜文字tab 页。
3. 大大优化了ConversationListFragment,ConversationFragment 界面的性能,在接收大量离线消息,上下滚动上性能得到很大提升。
4. ConversationListFragment,ConversationFragment开放了更多接口,开发者只需要继承对应的 fragment,override 其中的方法即可。
5. 移除了 InputProvider 类,+ 号区域中的按钮添加方式发生了改变,具体使用参考下面的说明及使用方法。
6. 以上修改目的让开发者使用起来更简单、快捷。

详细说明:

1. 输入区域扩展栏对外接口类为 RongExtension。
2. IPluginModule 是开发者自定义“+”号区域展开后的 item 接口类,开发者只需要实现此类。旧版本的 InputProvider 类被移除,其中的逻辑流程是一致的,只需要拷贝既可。
3. IEmoticonTab 是开发者自定义 表情 tab 页接口类,开发者只需要实现此类。此为 sdk 新增接口。
4. IExtensionModule 是开发者用自定义包含 IPluginModule 和 IEmoticonTab 的接口类,开发者只需要实现此类,并在 getPluginModules,getEmoticonTabs 两个回调中提供 b, c 中实例化后的对象。最后通过 RongExtensionManager 进行注册即可。
5. 内置了根据高德地图的地理位置、实时位置共享功能,如果开发者想在”+”号区域添加,只需要加入 DefaultLocationPlugin(地理位置),RealTimeLocationPlugin(实时位置) 或者 CombineLocationPlugin(地理位置和实时位置聚合),并且 sdk 中要包含 amap 相关 jar。
6. SDK 中包含默认的输入栏 DefaultExtensionModule,开发者可以通过继承此类做修改,具体参考:“5. 如何移除、调整 RongExtension 内置插件、表情功能”。
7. SDK 目录结构发生了变化:支持IMLib、IMKit、CallLib、CallKit、红包、地理位置 独立下载。

1)开发者在集成时,需要将 IMLib、IMKit、CallLib、CallKit、红包 分别以 module 的方式加载到 Android Studio 中。
2)如果不需要 Call 、红包功能,只需要将对应 module 移除即可。
3)LocationLib 对应高德地图 jar,如果使用 SDK 内置地理位置、位置共享功能,只需要将 jar 放置在开发者 app 的 libs 目录下,IMKit 中默认就会在“+”号区域显示位置功能。
4)PushLib 对应小米 jar,如果用到了小米推送,需要将 jar 放置在开发者 app 的 libs 目录下。

一. 如何替换输入框背景、图片

1.输入框布局文件是 rc_ext_extension_bar.xml,它是整个输入框的容器, 内部有对各部分组件功能描述。
2.EditText 布局文件是 rc_ext_input_edit_text.xml,如果想要替换背景,直接修改即可。
3.语音输入布局文件是 rc_ext_voice_input.xml。

二. 如何获取 RongExtension 实例

1. 目前 IMKit 中已经在布局文件中 rc_fr_conversation.xml 默认添加了 RongExtension 模块。
2. 开发者只需要继承 ConversationFragment, 在 onCreateView 通过 view.findViewById() 找到 RongExtension 模块即可。
3. 还可以通过 ConversationFragment 访问到 RongExtension 中各个组件被点击的事件,及内部 EditText 文本变化等方法。

—————————代码——————————-
<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”@color/rc_normal_bg”>

<io.rong.imkit.RongExtension
app:RCStyle=”SCE” //目前支持 5 种模式
android:id=”@+id/rc_extension”
android:layout_alignParentBottom=”true”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_above=”@android:id/toggle”/>

<fragment
android:id=”@android:id/list”
android:name=”io.rong.imkit.fragment.MessageListFragment”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:layout_above=”@id/rc_extension”/>
</RelativeLayout>
—————————结束——————————-

—————————代码——————————-
public class TestFragment extends ConversationFragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
mRongExtension = (RongExtension) view.findViewById(R.id.input_board);
return view;
}


/**
* 点击 “+” 号区域, 回调中携带 ViewGroup
*
* @param v “+” 号 view 实例
* @param extensionBoard 用于展示 plugin 的 ViewGroup
*/
@Override
public void onPluginToggleClick(View v, ViewGroup extensionBoard) {
super.onPluginToggleClick(v, extensionBoard);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
super.beforeTextChanged(s, start, count, after);
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
super.onTextChanged(s, start, before, count);
}

/**
* Extension 收起。
*/
public void onExtensionCollapsed() {
super.onExtensionCollapsed();
}

/**
* Extension 已展开。
*
* @param h Extension 展开后的高度。
*/
public void onExtensionExpanded(int h){
super.onExtensionExpanded(h);
}

}
—————————End——————————-

三. 动态修改 RongExtension 样式、客服输入模式

SDK 目前支持 5 中输入模式,可以通过 RongExtension 中的如下方法:
—————————代码——————————-
/**
* 设置 ExtensionBar 样式.
*
* @param style 目前支持 5 种样式,参照: {@link io.rong.imkit.InputBar.Style}
*/
public void setInputBarStyle(InputBar.Style style);
“`
“`
/**
* 设置 ExtensionBar 客服输入模式
*
* @param mode 输入模式, 参照: {@link CustomServiceMode}
*/
public void setExtensionBarMode(CustomServiceMode mode)
—————————结束——————————-

四. 如何自定义 IExtensionModule

1 . RongExtension 对外有一个 RongExtensionManager 管理器类,开发者可以注册自定义的 IExtensionModule,也可以注销已注册的 IExtensionModule。

—————————代码——————————-
/**
* 注册自定义的 {@link IExtensionModule},注册后,可以通过 {@link #getExtensionModules()} 获取已注册的 module
* 注意:请在 SDK 初始化后 {@link RongIM#init(Context)},调用此方法注册自定义 {@link IExtensionModule}
*
* @param extensionModule 自定义模块。
* @throws IllegalArgumentException IExtensionModule 参数非法时,抛出异常
*/
public void registerExtensionModule(IExtensionModule extensionModule)
“`
“`
/**
* 注销 {@link IExtensionModule} 模块
*
* @param extensionModule 已注册的 IExtensionModule 模块
* @throws IllegalArgumentException IExtensionModule 参数非法时,抛出异常
*/
public void unregisterExtensionModule(IExtensionModule extensionModule)
—————————结束——————————-
—————————代码——————————-
/**
* 获取已注册的模块。
*
* @return 已注册的模块列表
*/
public List<IExtensionModule> getExtensionModules()
—————————End——————————-

2 . 开发者需要实现 IExtensionModule 接口类,并调用RongExtensionManager.getInstance() 的注册接口,将自定义的

IExtensionModule 注册到管理器中。
IExtensionModule 包含两个生命周期:1) SDK connect 连接、接收消息、断开时同步状态给 IExtensionModule;2) IExtensionModule 被 View 加载、销毁。

—————————代码——————————-
public interface IExtensionModule {
/**
* SDK 初始化。
* 用户可以在该方法中注册自定义消息、注册消息模板、初始化自己的模块。
*
* @param appKey 应用唯一 key。
*/
void onInit(String appKey);

/**
* SDK 开始连接。
*
* @param token 用户连接时身份 id。
*/
void onConnect(String token);

/**
* 进入会话后,Extension 加载所有注册的 module。
* module 可以持有并使用 Extension.
* 注意:如果 module 持有 Extension 对象,需要在 onDetachedFromExtension 回调时释放,否则会有内存泄露。
*
* @param extension Extension 对象。
*/
void onAttachedToExtension(RongExtension extension);

/**
* 退出会话,Extension 释放所有已加载的 module。
* 注意:如果 module 持有 Extension 对象,需要在该回调时释放,否则会有内存泄露。
*/
void onDetachedFromExtension();

/**
* SDK 接收到消息后,通过此方法路由给对应的模块去处理。
* 用户可以根据自己注册的消息,有选择性的去处理接收到的消息。
*
* @param message 消息实体。
*/
void onReceivedMessage(Message message);

/**
* 用户可以根据不同的会话,配置 “+” 号区域插件。
* 可以配置一个插件,也可以同时配置多个插件。extension 展示所有返回的插件列表。
* 注意:如果用户没有配置插件,此方法可以不用实现。
*
* @param conversationType 会话类型。
* @return 插件列表。
*/
List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType);

/**
* 在会话中可以配置多个表情 tab,也可以配置单个表情 tab。
* 配置后,所有的会话中都会显示此 tab。
* 注意:如果用户没有配置表情,此方法可以不用实现。
*
* @return 表情 tab 列表。
*/
List<IEmoticonTab> getEmoticonTabs();

/**
* SDK 断开连接。
*/
void onDisconnect();
}
—————————结束——————————-

1. 实现了此类以后,如果想自定义插件,只需要在List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) 方法回调时,根据对应的会话类型提供自定义的 IPluginModule 插件即可;

2. 同理,如果自定义表情 tab 页,只需要实现List<IEmoticonTab> getEmoticonTabs()接口。
Plugin 和 Tab 都有对应的接口类,还需要实现对应的接口类;

—————————代码——————————-
public interface IPluginModule {

/**
* 获取 plugin 图标
*
* @param context 上下文
* @return 图片的 Drawable
*/
Drawable obtainDrawable(Context context);

/**
* 获取 plugin 标题
*
* @param context 上下文
* @return 标题的字符串
*/
String obtainTitle(Context context);

/**
* plugin 被点击时调用。
* 1. 如果需要 Extension 中的的数据,可以调用 Extension 相应的方法获取。
* 2. 如果在点击后需要开启新的 activity,可以使用 {@link Activity#startActivityForResult(Intent, int)}
* 或者 {@link RongExtension#startActivityForPluginResult(Intent, int, IPluginModule)} 方式。
* <p/>
* 注意:不要长期持有 fragment 或者 extension 对象,否则会有内存泄露。
*
* @param extension Extension 对象。
*/
void onClick(Fragment currentFragment, RongExtension extension);

/**
* activity 结束时返回数据结果。
* <p/>
* 在 {@link #onClick(Fragment, RongExtension)} 中,你可能会开启新的 activity,你有两种开启方式:
* <p/>
* 1. 使用系统中 {@link Activity#startActivityForResult(Intent, int)} 开启方法
* 这就需要自己在对应的 Activity 中接收处理 {@link Activity#onActivityResult(int, int, Intent)} 返回的结果。
* <p/>
* 2. 如果调用了 {@link RongExtension#startActivityForPluginResult(Intent, int, IPluginModule)} 开启方法
* 则在 Activity 中接收到 {@link Activity#onActivityResult(int, int, Intent)} 后,
* 必须调用 {@link RongExtension#onActivityPluginResult(int, int, Intent)} 方法,RongExtension 才会将数据结果
* 通过 IPluginModule 中 onActivityResult 方法返回。
* <p/>
*
* @param requestCode 开启 activity 时请求码,不会超过 255.
* @param resultCode activity 结束时返回的数据结果.
* @param data 返回的数据.
*/
void onActivityResult(int requestCode, int resultCode, Intent data);
}
“`
“`
public interface IEmoticonTab {

/**
* 构造 tab 的小图标,用于显示在 tab bar中。
*
* @param context 应用上下文。
* @return 图标的 drawable,不能为 null。
*/
public Drawable obtainTabDrawable(Context context);

/**
* 构造 table 页面。
*
* @param context 应用上下文。
* @return 构造后的 table view,不能为 null。
*/
public View obtainTabPager(Context context);

/**
* 表情面板左右滑动时,回调此方法。
*
* @param position 当前 table 的位置。
*/
public void onTableSelected(int position);
}
—————————结束——————————-

五. 如何移除、调整 RongExtension 内置插件、表情功能

1. IMKit 中实现了一个默认的 IExtensionModule : DefaultExtensionModule;
2. 开发者可以继承 DefaultExtensionModule,重写getPluginModules(Conversation.ConversationType conversationType) 方法和 getEmoticonTabs()
3. 查找已注册的 Module 并删除,替换成自定义的 Module

—————————代码——————————-
List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
IExtensionModule defaultModule = null;
//查找默认已注册模块
for (IExtensionModule module : moduleList) {
if (module instanceof DefaultExtensionModule) {
defaultModule = module;
break;
}
}
if (defaultModule != null) {
//移除已注册的默认模块,替换成自定义模块RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
RongExtensionManager.getInstance().registerExtensionModule(new SealExtensionModule());
}
—————————结束——————————-

—————————代码——————————-
public class SealExtensionModule extends DefaultExtensionModule {

@Override
public List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) {
List<IPluginModule> pluginModuleList = new ArrayList<>();
IPluginModule image = new ImagePlugin();
IPluginModule location = new DefaultLocationPlugin();
IPluginModule audio = new AudioPlugin();
IPluginModule video = new VideoPlugin();
IPluginModule file = new FilePlugin();

if (conversationType.equals(Conversation.ConversationType.GROUP) ||
conversationType.equals(Conversation.ConversationType.DISCUSSION) ||
conversationType.equals(Conversation.ConversationType.PRIVATE)) {
pluginModuleList.add(image);
pluginModuleList.add(location);
pluginModuleList.add(audio);
pluginModuleList.add(video);
pluginModuleList.add(file);
} else {
pluginModuleList.add(image);
}

return pluginModuleList;
}

@Override
public List<IEmoticonTab> getEmoticonTabs() {
return super.getEmoticonTabs();
}
}
—————————结束——————————-

六. ConversationFragment新增的开放接口

以下接口需要开发者自定义一个类继承自ConversationFragment,然后重写下面的方法。

1. onReadReceiptStateClick():群组消息阅读回执状态的点击事件。
2. onWarningDialog():会话界面的弹出窗口。例如弹出“聊天室加入失败”
3. onSelectCustomerServiceGroup():客服选择分组弹出窗口。

七. 重新设计会话列表、会话页面 item 长按 popup 菜单,增加弹出窗口 OptionsPopupDialog 工具类

—————————代码——————————-
/**
* onItemLongClick为会话列表item、会话页面message item的长按回调
* 如果重新定义长按菜单,请参考开发文档
* [会话列表操作监听](http://www.rongcloud.cn/docs/android.html#5、会话列表操作监听)
* [会话界面操作的监听器](http://www.rongcloud.cn/docs/android.html#6、会话界面操作的监听器)
*/
@Override
public void onItemLongClick(final View view, int position, final TextMessage content, final UIMessage message) {

String[] items = new String[] {view.getContext().getResources().getString(R.string.rc_dialog_item_message_delete)};
/**
* newInstance() 初始化OptionsPopupDialog
* @param items弹出菜单功能选项
* setOptionsPopupDialogListener()设置点击弹出菜单的监听
* @param which表示点击的哪一个菜单项,与items的顺序一致
* show()显示pop dialog
*/
OptionsPopupDialog.newInstance(view.getContext(), items).setOptionsPopupDialogListener(new OptionsPopupDialog.OnOptionsItemClickedListener() {

@Override
public void onOptionsItemClicked(int which) {
if (which == 0) {
RongIM.getInstance().deleteMessages(new int[] {message.getMessageId()}, null);
}
}
}).show();

}
—————————结束——————————-

八. 开发红包功能

1. 融云官网提供 RedPacket Module 下载,开发者需要在自己应用的 build.gradle 文件中添加依赖 compile project(‘:RedPacket’).
2. SDK会默认加载红包模块,并在私人、群组会话”+”号区域出现红包插件(暂不支持其他会话类型).
3. 开发者需要实现 RongIM#setGroupMembersProvider(IGroupMembersProvider) 方法,用于红包功能中展示群组成员信息.
3. 红包模块提供如下接口,进入”我的钱包”界面:

—————————代码——————————-
/**
* 进入我的钱包页面
* @param activity :从哪个activity的跳转
*/
JrmfClient.intentWallet(Activity activity);
进入到我的钱包页面
—————————结束——————————-