
IM即时通讯
安全可靠、全球互通

实时音视频
流畅稳定、省钱省力
回答:
在你的 application 类中 onCreate() 方法中调用初始化方法
/** * 初始化 SDK,在整个应用程序全局,只需要调用一次。 * * @param appKey 应用的app key. * @param context 应用上下文。 */ public static void init(Context context, String appKey)
注意:SDK 在初始化成功后,会有至少两个进程:主进程,ipc;在不支持系统推送的机型上,还会有 push 进程。
在特定机型上出现此问题,一般是因为 64k 问题,应用程序引用库太多,放法数超过 65536,解决方法 https://support.rongcloud.cn/ks/NTM5
从 App Server 获取到 token 后,客户端应该做 token 的缓存(存储在 sharepreference 中)
token 的有效期是开发者后台设置的,可以永久有效,也可以定期失效
当链接时,connect() 方法回调 onTokenIncorrect() 时,应从 App Server 上重新获取 token 并缓存,使用新获取的 token 再次链接
调用 SDK 的设置网络状态监听方法,之后所有的链接状态变化都会通过此方法回调通知
/** * 设置连接状态变化的监听器。 * * @param listener 连接状态变化的监听器。 */ public static void setConnectionStatusListener(final RongIMClient.ConnectionStatusListener listener)
在你的登录界面类中调用连接方法
/** * <p>连接服务器,在整个应用程序全局,只需要调用一次,需在 {@link #init(Context)} 之后调用。</p> * <p>如果调用此接口遇到连接失败,SDK 会自动启动重连机制进行最多10次重连,分别是1, 2, 4, 8, 16, 32, 64, 128, 256, 512秒后。 * 在这之后如果仍没有连接成功,还会在当检测到设备网络状态变化时再次进行重连。</p> * * @param token 从服务端获取的用户身份令牌(Token)。 * @param callback 连接回调。 * @return RongIMClient IM 客户端核心类的实例。 */ public static RongIMClient connect(final String token, final ConnectCallback callback)
可以使用此链接检查:https://rongcloud.github.io/websdk-demo/connect-check.html
使用上述连接成功后,此账户收到的消息都会打印到页面中
动态获取 token 需要在 APP server 端获取
参考文档:http://www.rongcloud.cn/docs/server.html#user_get_token
token错误,请您检查客户端初始化使用的AppKey和您服务器获取token使用的AppKey是否一致
token过期,是因为您在开发者后台设置了token过期时间,您需要请求您的服务器重新获取token并再次用新的token建立连接。
请确认一下 AppKey 和 token 是否匹配。
请在开发者后台确认 token 是否在有效期。
请使用工具:https://rongcloud.github.io/websdk-demo/api-test.html 来测试一下能否链接成功。
首先按照文档:http://www.rongcloud.cn/docs/android.html#message_customize实现自定义消息
需要注意的是:消息在 ipc 和主进程间需要跨进程,涉及到序列化问题,需要严格控制和检查 json 中是否有 null 字段问题
首先检查数据库中 rct_message 表中,相应的消息中是否有用户信息:如果没有,可以就是发送端没有设置成功用户信息
数据库位置:需要 root 手机或者模拟器
老版本:/data/data/app包名/files/appkey/userId/storage
新版本:包含三个文件,/data/data/app包名/files/appkey/userId/ 目录下的 “storage”、“storage-shm”、“storage-wal”。将这三个文件拷贝到统一路径下,打开 storage 文件。
如果数据库消息表中包含用户信息,需要检查用户信息是否完整:比如 userId 是否正确
在你的 application 类中设置用户、群组信息提供者,当 SDK 需要展示头像时,会回调提供者的回调方法
如果是异步获取信息,你可以先在回调方法中先返回 null,再取到信息后,调用如下方法再次刷新:
/** * 刷新用户缓存数据。 * * @param userInfo 需要更新的用户缓存数据。 */ public void refreshUserInfoCache(UserInfo userInfo) /** * 刷新群组缓存数据。 * * @param group 需要更新的群组缓存数据。 */ public void refreshGroupInfoCache(Group group)
头像、名字信息第一次加载成功后,SDK 会做数据库存储。SDK 在展示头像、名字信息时如果能从数据库中取出,就不会再回调信息提供者
所以,如果信息变更,需要你重新调用刷新接口,做强制刷新
kit 中的发消息接口在发送消息时,会同时将消息展示在界面上
问题表现:SDK 的 ipc 进程启动不起来,连接不成功
方法一:在 build.gradle 中把 targetSdkVersion 改小于24
方法二:apk中带上需要的so文件,这儿是libsqlite.so下载附件中的so文件,放到对应的文件夹下,如libs/armv7-abi/libsqlite.so,并注意你的gradle是否引用了这个目录,如 jniLibs.srcDirs = ['libs']
通过Android Studio的Analyze APK功能[Build -> Analyze APK...], 或直接解开apk包,查看是apk的lib目录下是否已包含libsqlite.so文件 https://support.rongcloud.cn/ks/NzIw
跳转原理是通过 manifest 中的 intent-filter 配置实现的:http://www.rongcloud.cn/docs/android.html#other_intent-filter
在被跳转的界面中判断是否是来自 push 的消息,如果是,需要做 connect()连接,(注意:此方法和 SDK 自动重连不冲突)
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { ... Intent intent = getIntent(); Uri data = intent != null ? intent.getData() : null; String pushParam = data != null ? data.getQueryParameter("isFromPush") : null; isPush = pushParam != null && pushParam.equals("true"); boolean isBackgroundNotify = pushParam != null && pushParam.equals("false"); //push 通知 if (isPush //应用被杀死,后台通知依然存在 || (isBackgroundNotify && RongIMClient.getCurrentConnectionStatus().equals(RongIMClient.ConnectionStatusListener.ConnectionStatus.DISCONNECTED)) //界面被回收恢复 || (savedInstanceState != null && !RongIMClient.getCurrentConnectionStatus().equals(RongIMClient.ConnectionStatusListener.ConnectionStatus.CONNECTED))) { RongIM.connect(token, callback); } ... }
历史消息:SDK 会对消息做本地存储,在会话中显示的都是本地存储的消息
/** * <p> * 获取指定类型,targetId 的N条历史消息记录。通过此接口可以根据情况分段加载历史消息,节省网络资源,提高用户体验。 * 该接口不支持拉取聊天室 {io.rong.imlib.model.Conversation.ConversationType#CHATROOM} 历史消息。 * </p> * * @param conversationType 会话类型。 * @param targetId 目标 Id。根据不同的 conversationType,可能是用户 Id、讨论组 Id、群组 Id。 * @param oldestMessageId 最后一条消息的 Id,获取此消息之前的 count 条消息,没有消息第一次调用应设置为:-1。 * @param count 要获取的消息数量。 * @param callback 获取历史消息记录的回调,按照时间顺序从新到旧排列。 */ public void getHistoryMessages(final Conversation.ConversationType conversationType, final String targetId, final int oldestMessageId, final int count, final ResultCallback<List<Message>> callback)
历史消息云存储:
当本地数据库的消息展示完成以后,如果你开通了历史消息云存储的服务,在会话中下拉,会继续加载消息,这部分消息就是从服务器端拉取的历史消息;
清空会话中的历史消息,仅仅清除的是本地存储的历史消息,如果你开通了历史消息云存储服务,在会话中下拉,依然能拉取历史消息,这部分消息就是从服务器端拉取的历史消息;
/** * <p>获取融云服务器中暂存,特定类型,targetId 的N条(一次不超过40条)历史消息记录。通过此接口可以根据情况分段加载历史消息,节省网络资源,提高用户体验。</p> * <p>区别于 {@link #getHistoryMessages},该接口是从融云服务器中拉取。通常用于更换新设备后,拉取历史消息。 * 公众服务会话 {@link io.rong.imlib.model.Conversation.ConversationType#APP_PUBLIC_SERVICE} * {@link io.rong.imlib.model.Conversation.ConversationType#PUBLIC_SERVICE} </p> * * @param conversationType 会话类型。 * @param targetId 目标 Id。根据不同的 conversationType,可能是用户 Id、讨论组 Id、群组 Id。 * @param dateTime 从该时间点开始获取消息。即:消息中的 sentTime;第一次可传 0,获取最新 count 条。 * @param count 要获取的消息数量,最多 40 条。 * @param callback 获取历史消息记录的回调,按照时间顺序从新到旧排列。 */ public void getRemoteHistoryMessages(final Conversation.ConversationType conversationType, final String targetId, final long dateTime, final int count, final ResultCallback<List<Message>> callback)
消息补偿:是一项收费服务器,体现在多端登录的时候消息同步。消息补偿可以设置时间:3天或7天;当客户端第一次(仅仅是第一次)安装登录,就会把这段时间内的所有消息下发下来
设置 App 级别的扩展区域,通过这个方法设置后,每个会话界面展示的都是一样的:http://support.rongcloud.cn/kb/NTU1
继承 ConversationFragment 然后根据布局中的 id 获取到 Extension 对象
public class ChatFragment extends ConversationFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { containerView = (RelativeLayout) super.onCreateView(inflater, container, savedInstanceState); extension = (RongExtension) containerView.findViewById(io.rong.imkit.R.id.rc_extension); return containerView; } }
根据当前页面的 ConversationType 和 TargetId,调用 Extension 中的对应方法:
/** * 动态在 plugin 区域的末尾增加一个 plugin 。 * * @param pluginModule 增加的 plugin */ public void addPlugin(IPluginModule pluginModule) /** * 移除指定的 plugin * * @param pluginModule 指定 plugin */ public void removePlugin(IPluginModule pluginModule) /** * 获取当前所有 Plugin 列表 * * @return 已加载的 plugin 列表 */ public List<IPluginModule> getPluginModules()