会话服务是AIMSDK提供的重要基础能力,分为单聊和群聊,单聊会话进行扩展后即为群聊。本文为您介绍会话服务中的会话模型,会话管理和群聊会话。全文的示例代码均以Android代码为例。

会话模型

群聊是单聊会话的扩展,模型中有大部分字段是公用的,部分字段只用于单聊或者只用于群聊。

字段 类型 描述
appCid String 会话ID。
type AIMConvType 会话类型(单聊、群聊)。
status AIMConvStatus 会话状态(正常、隐藏、离线、被踢、解散)。
createAt long 会话创建的服务端时间。
modifyTime long 获取会话最后更新时间,拉取会话列表时,SDK会根据此字段排序。lastMessage变更或者置顶事件会导致modifyTime更改。
redPoint int 会话红点数。
draft String 会话草稿。
muteNotification boolean 是否开启免打扰。
topRank long 置顶字段,topRank值越小,说明置顶操作越早,置顶位置越靠前。
extension HashMap< String, String > 扩展字段。
user_extension HashMap< String, String > User维度的会话扩展字段。
local_extension HashMap< String, String > 本地会话扩展字段(不同步至服务端)。
hasLastMsg boolean 是否有最后一条消息。
lastMsg AIMPubMessage 会话的最后一条消息。
joinTime long 会话加入时间(主要用于群聊)。
readReceiptsEnabled boolean 是否启动已读回执。
userids(单聊特有) ArrayList<String> 会话参与者用户ID。
ownerUid(群聊特有) String 群主的用户ID。
title(群聊特有) String 群会话标题。
icon(群聊特有) String 群头像。
memberCount(群聊特有) int 群成员人数。
silenceAll(群聊特有) boolean 是否禁言所有人。
silenceStatus(群聊特有) AIMGroupSilenceStatus 禁言状态(普通状态、白名单、黑名单)。
silenceEndtime(群聊特有) long 禁言截止时间。
memberPermissions(群聊特有) ArrayList< AIMGroupPermission > 群成员权限(比如群成员是否可以改标题头像)。

会话管理

以下说明以及示例均以单聊为例,关于群聊信息,请参见群组管理

  • 创建会话

    通过调用AIMConvServiceCreateSingleConversation接口创建单聊会话。

    CreateSingelConvParam接口中填写聊天双方的UserId。

    说明CreateSingleConvParam接口中的isLocal字段为true时,该会话不会同步到服务器,本地会话的状态为CONV_STATUS_OFFLINE
    示例代码,如下所示:
    // 自己的UserId
    String self = UserUtil.getCurrentUserId();
    // 对方的UserId
    String other = uid;
    ArrayList<String> uidlist = new ArrayList<>();
    uidlist.add(self);
    uidlist.add(other);
    StringBuilder sb = new StringBuilder();
    // appCid可以填写也可以不填写,但是不填写appCid的情况下,
    // IMPaaS会默认创建自定义单聊,自定义单聊cid结构为 $3$UserId1:UserId2。
    // 自定义单聊需要App服务端接入IMPaaS的回调,否则会报错。
    // 让IMPaaS创建标准单聊的方式是传入参数param中自己定义appCid,
    // 定义结构为 $1$UserId1:UserId2  其中(字典序小的userid靠前)
    sb.append("$1$");
    if (self.compareTo(other) > 0) {
      sb.append(other);
      sb.append(":");
      sb.append(self);
    } else {
      sb.append(self);
      sb.append(":");
      sb.append(other);
    }
    
    AIMPubConvCreateSingleConvParam param = new AIMPubConvCreateSingleConvParam();
    param.uids = uidlist;
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        .createSingleConversation(param, new AIMPubConvCreateSingleConvListener() {
          @Override
          public void onSuccess(AIMPubConversation AIMPubConversation) {
            AIMLog.e("createSingleConversation, onSuccess:" +
                     AIMPubConversation.getStatus());
            // AIMSDK执行接口成功,会话结果以onAddedConversations事件为准
          }
    
          @Override
          public void onFailure(DPSError DPSError) {
            if (DPSError.getCode() == 19) {
              AIMLog.toastWrapper("创建失败,该会话已存在");
            }
            AIMLog.e("createSingleConversation onFailure, code:" + DPSError);
          }
        });

    当单聊会话创建成功时,由于AIMSDK本地新增了一条会话条目,创建会话者会收到AIMPubConvListListeneronAddedConversations回调函数,用于通知给客户端。

    当单聊会话创建成功时,会话中的另一方不会马上收到会话创建的通知,直到创建会话者发送消息后,会话中的另一方才会通过AIMPubConvListListeneronAddedConversations回调函数看见新会话。

    回调函数的归属,如下表所示:
    回调函数 归属Listener 归属Service
    onAddedConversations AIMPubConvListListener AIMPubConvService
  • 获取会话

    通过调用AIMPubConvServicelistLocalConversationWithOffset接口获取会话列表。

    每个获取会话接口的简要介绍,如下表所示:

    接口 描述 参数
    listLocalConversationWithOffset 拉取会话列表,隐藏会话不会返回(拉取会话不需要rpc请求,SDK内部有同步会话机制)。
    • offset:从offset开始拉取,根据置顶及最后更新时间进行排序。
    • count:需要拉取的会话数量。
    • listener:监听器。
    listLocalConversationWithCid 拉取会话列表,隐藏会话不会返回(没有rpc请求)。
    • appCid:从指定会话ID开始拉取,若该值为空从第一个会话开始拉取。
    • count:需要拉取的会话数量。
    • listener:监听器。
    getConversation 获取会话ID对应的会话(本地没有则触发rpc)。
    • appCid:指定会话ID。
    • listener:监听器。
    getConversations 获取指定会话ID的会话(本地没有则触发rpc)。
    • appCid:指定会话ID列表。
    • listener:监听器。
    getLocalConversations 获取会话ID对应的会话(本地没有不触发rpc)。
    • appCid:指定会话ID列表。
    • listener:监听器。
    getSingleConversations 获取指定用户ID对应的会话(本地没有不会触发rpc)。
    • userId:指定的用户ID。
    • listener:监听器。
    getSingleConversationsWithUserId 获取指定用户ID对应的会话(本地没有不会触发rpc)。
    • userIds:指定的用户ID列表。
    • listener:监听器。
    listAllStatusLocalConvs 获取本地会话列表,包括所有状态的会话(也会返回隐藏的)。
    • offset:从offset开始拉取,根据置顶及最后更新时间进行排序。
    • count:需要拉取的会话数量。
    • listener:监听器。
  • 隐藏会话(本地消息数据保留)

    通过调用AIMConversationServiceHide接口隐藏会话列表,会话状态变为CONV_STATUS_HIDE。如果有新消息时,会话状态会恢复为CONV_STATUS_NORMAL

    示例代码,如下所示:
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        .hide(conversation.getAppCid(), new AIMConvServiceCompleteListener() {
          @Override
          public void onSuccess() {
            AIMLog.e("hide success");
            // 隐藏成功,客户端可以在UI上删除该会话
          }
    
          @Override
          public void onFailure(DPSError DPSError) {}
        });
  • 删除会话(本地消息数据删除)

    删除会话是物理删除本地DB,会删除会话相应的所有信息,不会发送RPC同步服务端。

    通过调用AIMPubConvServiceremoveLocalConversation接口实现删除会话。

    通常情况调用Hide接口隐藏会话,除非需要删除本地会话表中的消息数据。才需要调用removeLocalConversation接口删除会话。

    示例代码,如下所示:
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        .removeLocalConversation(conversation.getAppCid(),
                                 new AIMConvServiceCompleteListener() {
                                   @Override
                                   public void onSuccess() {
                                     // 删除会话成功
                                   }
    
                                   @Override
                                   public void onFailure(DPSError DPSError) {}
                                 });
  • 静音会话

    静音会话只是一个状态标识,供客户端实现静音会话的逻辑。会话变更、消息新增事件仍然会被广播。

    调用AIMPubConvServicemute接口实现静音会话,同时静音会话会标识该会话是否处于免打扰状态。

    示例代码,如下所示:
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        .mute(conversation.appCid, !conversation.muteNotification,
              new AIMConvServiceCompleteListener() {
                @Override
                public void onSuccess() {
                  AIMLog.e("mute or unmute success"); 
                  // 静音会话成功
                }
    
                @Override
                public void onFailure(DPSError dpsError) {}
              });
  • 会话置顶

    通过调用AIMPubConvServicesetTop接口实现会话置顶,接口中的top字段是boolean类型表示是否置顶。

    会话置顶会通过更新会话的topRank字段,表示置顶的先后顺序。topRank值越小,说明置顶操作越早,置顶位置越靠前,当topRank值为0时表示取消置顶。供客户端实现置顶会话和会话排序逻辑。

    示例代码,如下所示:
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        .setTop(conversation.getAppCid(), conversation.getTopRank() == 0,
                new AIMConvSetTopListener() {
                  @Override
                  public void onSuccess(long l) {
                    // 置顶会话成功,l为会话的topRank值
                  }
    
                  @Override
                  public void onFailure(DPSError DPSError) {
                    AIMLog.e("setTop onFailure, code:" + DPSError);
                  }
                });
  • 激活会话

    通过调用AIMPubConvServicesetActiveCid接口实现激活会话。激活会话后,会话将不再计算红点。如果您希望取消激活会话,传入appCid为空字符串即可。

  • 清空会话

    通过调用AIMPubConvServiceclear接口实现清空会话。清空会话会将清空本地缓存的所有消息数据,并且清除会话红点。

  • 清除会话红点

    清除会话红点可以清空消息的未读数(会话消息的未读数从n变为0),清除会话红点可以选择特定的会话调用clearRedPoint接口,也可以调用clearAllConvsRedPoint接口清除本地缓存的所有会话的红点。

  • 会话草稿

    通过调用AIMPubCovServiceupdateDraftMessage接口实现会话草稿。客户端可以将自己正在输入的文本信息作为会话草稿保存在本地,从而实现针对一个会话的草稿保存,会话草稿仅支持文本草稿。

  • 正在输入

    正在输入消息的客户端可以通过调用AIMPubConvServiceupdateTypingStatus接口更新正在输入状态。

    说明 updateTypingStatus接口不宜调用过于频繁,建议5s调用一次。

    发送者需要准确填写接收者的receiversId字段,并正在输入只对单聊会话有效。接收者会接收到AIMPubConvChangeListeneronConvTypingEvent回调。

    示例代码,如下所示:
    //事件发送方
    AIMPubModule.getModuleInstance(currentUserId())
        .getConvService()
        // 会话ID
        .updateTypingStatus(
            mCid,
            // 事件接收者
            mOtherUserId,
            // 事件类型
            AIMConvTypingCommand.CONV_TYPING_COMMAND_TYPING,
            // 正在输入的类型
            AIMConvTypingMessageContent.CONV_TYPING_MESSAGE_TYPE_TEXT,
            // 接口监听器可以为空,因为正在输入事件的成功与否并不关键
            null);
    回调函数 归属Listener 归属Service
    onConvTypingEvent AIMPubConvChangeListener AIMPubConvChangeListener
  • 会话变更事件

    当会话因为本地调用时,例如隐藏会话、删除会话、静音会话、会话草稿等接口导致会话属性发生变化,或者IMPaaS服务端推送导致会话变更,AIMSDK会通过AIMPubConvListListenerAIMPubConvChangeListener两个监听器的相关回调函数通知客户端。

    通过调用AIMPubConvServiceaddConvChangeListeneraddConvListListener接口完成监听器的注册。

    说明 客户端可以多次调用注册监听器接口,AIMSDK会在有会话变更事件时依次回调每个监听器的回调函数。

群组管理

群聊会话是单聊会话的扩展,群聊的扩展能力由AIMPubGroupService类提供。

  • 创建群聊会话

    通过调用createGroupConversation接口创建群聊会话。

    示例代码,如下所示:
    AIMPubGroupCreateGroupConvParam param = new AIMPubGroupCreateGroupConvParam();
    // 构造群成员列表
    param.userInfos = new ArrayList<>();
    // uid必须填写,其他选填
    param.userInfos.add(new AIMPubGroupUserInfo(currentUserId(), null, null));
    param.userInfos.add(new AIMPubGroupUserInfo(mOtherUserId, null, null));
    param.userInfos.add(new AIMPubGroupUserInfo(userId.uid, null, null));
    // 群标题
    param.title = title;
    
    AIMPubModule.getModuleInstance(currentUserId())
        .getGroupService()
        .createGroupConversation(param, new AIMPubGroupCreateGroupConvListener() {
          @Override
          public void onSuccess(AIMPubConversation AIMPubConversation) {
            AIMLog.d("Create group success: ", AIMPubConversation.getTitle());
          }
    
          @Override
          public void onFailure(DPSError DPSError) {
            AIMLog.e("Create group failed", DPSError.toString());
          }
        });
  • 群权限设置
    会话属性中,预留了memberPermissions字段供客户端扩展实现群权限,memberPermissions中是一组权限信息列表AIMGroupPermission,每一条权限信息AIMGroupPermissionpermisssionGroup由客户端自行定制,status表示该权限的状态(例如无权限、有权限、废弃)。客户端可以自由根据群权限字段定制每个群组管理接口的调用权限,群权限的设置通过AIMPubGroupServicesetMemberPermission接口实现。
    说明 客户端可以借助会话属性中的ownerId字段标识群主。群主可以直接执行群操作,不需要检查权限。
  • 添加群成员

    给指定会话IdappCid的会话添加群成员,调用AIMPubGroupServiceaddMembers接口实现。所有群成员会通过AIMPubGroupMemberChangeListeneronAddedMembers回调得知有人加入群聊的通知。

  • 移除群成员

    将指定用户IdUserId的用户移除一个群聊,调用AIMPubGroupServiceremoveMembers接口实现。所有群成员都会通过AIMPubGroupMemberChangeListeneronRemovedMembers回调得知有人被踢出群聊的通知。

  • 禁言黑白名单

    通过AIMGroupPermissionaddSilencedBlacklistaddSilencedWhitelist接口可以添加禁言黑名单和禁言白名单,禁言黑名单与禁言白名单对应的是会话属性中的silenceStatus字段。可以通过调用removeSilenceBlacklistremoveSilenceWhitelist接口取消禁言黑名单与禁言白名单。调用silenceAll接口可以禁言所有人,即让所有群成员的会话属性中silenceAll字段为true,也可以调用cancelSilenceAll取消禁言所有人。

    说明 添加禁言黑名单需要设置禁言结束时间,该时间会更新到被禁言者会话属性的silenceEndtime字段。
  • 拉取群成员
    拉取群成员可以使用以下两个接口:
    • 通过调用listLocalMembers接口可以拉取本地缓存中的群成员,接口中的cursor字段表示成员游标,count字段表示希望拉取多少个群成员。支持在群成员的全体列表上逐步拉取单个群成员,客户端可以借此方式实现分页功能。
    • 通过调用listAllMembers接口,AIMSDK向IMPaaS服务端同步指定会话ID的群成员列表,并将所有群成员返回。
  • 转移群主

    通过调用setOwner接口可以实现转移群主功能,更新群成员会话属性的ownerUid字段。通常情况下setOwner接口,只有当前群的群主才可以调用,这些权限判断需要由客户端自行实现。

  • 解散群

    通过调用dismiss接口可以解散群,所有群成员都会通过AIMPubGroupChangeListeneronGroupDismissed回调得知群被解散的通知。

  • 离开群

    通过调用leave接口可以离开指定的群,所有群成员都会通过AIMPubGroupMemberChangeListeneronRemovedMembers回调得知有人离开群聊的通知。

  • 更新群信息

    更新群信息的操作包括群通知、群标题、群员昵称、群员角色、群头像,分别调用updateAnnouncememntupdateDefaultTitleupdateGroupMemberNickupdateGroupMemberRoleupdateIcon接口实现,更新信息会通知给所有群成员,AIMSDK会通过AIMPubGroupChangeListener的相应回调函数通知客户端。

  • 群组变更事件

    当群组信息、群组成员、禁言状态等发生变化时,IMSDK会通过AIMPubGroupChangeListenerAIMPubGroupMemberChangeListener两个监听器的相关回调函数通知客户端。

    由客户端调用AIMPubGroupServiceaddGroupChangeListeneraddGroupMemberChangeListener接口注册监听器。

    说明 客户端可以多次调用注册监听器接口,AIMSDK在有会话变更事件时依次回调每个监听器的回调函数。