好友管理
本文档面向使用融云即时通讯 Flutter IMLib SDK 的开发者,介绍如何在 Flutter 端完成好友添加、好友请求处理、好友资料维护以及好友事件监听等能力。您将学会如何调用 RCIMIWEngine 的接口,通过学习示例代码,在业务中落地好友体系。
此功能从 5.32.0 版本开始支持,请确保 SDK 版本满足要求。
开通服务
信息托管服务默认开通,您可以直接体验好友相关接口。
好友事件监听
在调用 RCIMIWEngine.connect 之前设置好友事件监听器,可以在本端实时接收好友新增、删除、请求状态变化等通知。以下回调属性都定义在 RCIMIWEngine 中 :
| 回调 | 触发场景 |
|---|---|
onFriendAdded | 好友关系建立,包含好友基本信息与操作时间 |
onFriendDeleted | 好友被解除,返回被删除的用户 ID 列表 |
onFriendsClearedFromServer | 服务端清空好友列表后的广播 |
onFriendInfoChangedSync | 同账号多端收到好友备注、扩展资料更新 |
onFriendApplicationStatusChanged | 好友申请的状态变化(未处理、已同意、已拒绝) |
好友事件属于状态同步行为,即便应用未设置监听,服务端也会向 SDK 推送最新状态,该通道会计入消息分发与下行数据量。
final RCIMIWEngine? engine = IMEngineManager().engine;
engine?.onFriendAdded = (
RCIMIWFriendType? friendType,
String? userId,
String? name,
String? portraitUri,
int? operationTime,
) {
debugPrint('onFriendAdded => $userId $friendType');
};
engine?.onFriendDeleted = (
RCIMIWFriendType? friendType,
List<String>? userIds,
int? operationTime,
) {
debugPrint('onFriendDeleted => $userIds');
};
engine?.onFriendInfoChangedSync = (
String? userId,
String? remark,
Map<dynamic, dynamic>? extProfile,
int? operationTime,
) {
debugPrint('onFriendInfoChangedSync => $userId $remark $extProfile');
};
engine?.onFriendApplicationStatusChanged = (
String? userId,
RCIMIWFriendApplicationType? applicationType,
RCIMIWFriendApplicationStatus? status,
RCIMIWFriendType? friendType,
int? operationTime,
String? extra,
) {
debugPrint('onFriendApplicationStatusChanged => $userId $status');
};
好友在线状态与资料变更
好友之间的在线状态、资料更新同样会由 SDK 维护并同步。若需要在变动时收到通知,可在连接前调用 subscribeEvent 并选择订阅类型:
RCIMIWSubscribeType.onlineStatus:好友在线状态RCIMIWSubscribeType.userProfile:好友托管资料
您需要通过开发者后台开启"客户端好友资料变更通知"和"客户端好友在线状态变更通知"功能后,才能使用此功能,实时接收好友之间的在线状态和用户资料变更通知。通知行为也会计入单聊消息的分发、下行数据统计。
具体订阅、查询接口与监听方式请参考 订阅用户在线状态 文档。
好友操作
添加好友
接口
addFriend(
String userId,
RCIMIWFriendType friendType,
String extra,
{IRCIMIWAddFriendCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userId | String | 目标用户 ID,可结合 用户搜索 能力获取 |
friendType | RCIMIWFriendType | 好友关系方向,当前仅支持 RCIMIWFriendType.both(双向好友) |
extra | String | 附加信息,长度 ≤ 128,用于 好友申请备注 |
callback | IRCIMIWAddFriendCallback? | 返回处理进度码(processCode)或错误码 |
单个用户最多可拥有 3000 个好友。
Android 侧 IRCIMIWAddFriendCallback.onSuccess 会把 processCode 原样透传给 Flutter,业务状态码例如 RC_FRIEND_NEED_ACCEPT 会在这里返回;iOS 侧 RCIMIWEngine.addFriend 则会把错误码传给 error block。因此,判断 processCode 时需要注意按平台区分回调,才能兼容两端的返回差异。
示例代码
final IRCIMIWAddFriendCallback callback = IRCIMIWAddFriendCallback(
onSuccess: (int? processCode) {
debugPrint('addFriend success, processCode=$processCode');
},
onError: (int? code) {
debugPrint('addFriend failed, code=$code');
},
);
final int? result = await IMEngineManager().engine?.addFriend(
'user1',
RCIMIWFriendType.both,
'请求添加好友',
callback: callback,
);
设置加好友权限
接口
setFriendAllowType(
RCIMIWFriendAllowType allowType,
{IRCIMIWOperationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
allowType | RCIMIWFriendAllowType | 当前用户的加好友策略 |
callback | IRCIMIWOperationCallback? | 成功 / 失败通知 |
RCIMIWFriendAllowType 枚举说明
| 枚举值 | 说明 |
|---|---|
free | 任何人直接添加好友 |
needVerify | 需要通过验证 |
noOneAllowed | 拒绝所有请求 |
RCIMIWFriendAllowType.notSet 仅在 Flutter 枚举中占位,实际业务场景没有意义。如果将该值传给 setFriendAllowType 等接口会直接触发参数错误,请不要使用。
示例代码
final IRCIMIWOperationCallback callback = IRCIMIWOperationCallback(
onSuccess: () => debugPrint('setFriendAllowType success'),
onError: (int? code) => debugPrint('setFriendAllowType error => $code'),
);
await IMEngineManager().engine?.setFriendAllowType(
RCIMIWFriendAllowType.needVerify,
callback: callback,
);
获取加好友权限
接口
getFriendAllowType({IRCIMIWGetFriendAllowTypeCallback? callback})
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
callback | IRCIMIWGetFriendAllowTypeCallback? | 返回当前权限枚举,或错误码 |
示例代码
final IRCIMIWGetFriendAllowTypeCallback callback = IRCIMIWGetFriendAllowTypeCallback(
onSuccess: (RCIMIWFriendAllowType? type) => debugPrint('current allowType=$type'),
onError: (int? code) => debugPrint('getFriendAllowType failed => $code'),
);
await IMEngineManager().engine?.getFriendAllowType(callback: callback);
权限生效说明
- 默认采用 AppKey 级别的配置:需要验证。
- 当用户单独设置后,以用户级别为准;未设置则继承 AppKey 策略。
| AppKey 权限 | 用户权限 | 最终结果 |
|---|---|---|
free / needVerify / noOneAllowed | 未设置 | 继承 AppKey 配置 |
| 任意 | 设置为 free / needVerify / noOneAllowed | 以用户设置为准 |
场景示例
- 无需验证:B 调用
setFriendAllowType(RCIMIWFriendAllowType.free),A 直接addFriend成功,IRCIMIWAddFriendCallback返回processCode = 0,双方触发onFriendAdded。 - 需要验证:B 配置
needVerify,A 调用addFriend后回调processCode = RCErrorCode.rcFriendNeedAccept (25461),双方收到onFriendApplicationStatusChanged,由 B 决定调用acceptFriendApplication或refuseFriendApplication。
解除好友
接口
deleteFriends(
List<String> userIds,
RCIMIWFriendType friendType,
{IRCIMIWOperationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userIds | List<String> | 需要解除关系的用户 ID,一次最多 100 个 |
friendType | RCIMIWFriendType | 解除的关系类型(仅 both) |
callback | IRCIMIWOperationCallback? | 成功 / 失败通知 |
示例代码
final IRCIMIWOperationCallback callback = IRCIMIWOperationCallback(
onSuccess: () => debugPrint('deleteFriends success'),
onError: (int? code) => debugPrint('deleteFriends failed => $code'),
);
await IMEngineManager().engine?.deleteFriends(
<String>['user1', 'user2', 'user3'],
RCIMIWFriendType.both,
callback: callback,
);
检查好友关系
接口
checkFriendsRelation(
List<String> userIds,
RCIMIWFriendType friendType,
{RCIMIWCheckFriendsRelationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userIds | List<String> | 待检查的用户,单次最多 20 个 |
friendType | RCIMIWFriendType | 目 前仅支持 both |
callback | RCIMIWCheckFriendsRelationCallback? | 成功返回 List<RCIMIWFriendRelationInfo> |
示例代码
final IRCIMIWCheckFriendsRelationCallback callback = IRCIMIWCheckFriendsRelationCallback(
onSuccess: (List<RCIMIWFriendRelationInfo>? result) {
debugPrint('relation result => ${result?.map((e) => e.toJson())}');
},
onError: (int? code) => debugPrint('checkFriendsRelation failed => $code'),
);
await IMEngineManager().engine?.checkFriendsRelation(
<String>['user1', 'user2'],
RCIMIWFriendType.both,
callback: callback,
);
好友申请操作
分页获取好友请求列表
接口
getFriendApplications(
List<RCIMIWFriendApplicationType> applicationTypes,
List<RCIMIWFriendApplicationStatus> status,
RCIMIWPagingQueryOption queryOption,
{IRCIMIWGetFriendApplicationsCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
applicationTypes | List<RCIMIWFriendApplicationType> | 需要查询的请求来源(发送 / 接收) |
status | List<RCIMIWFriendApplicationStatus> | 需要过滤的状态(未处理、已同意、已拒绝) |
queryOption | RCIMIWPagingQueryOption | 分页设置,包含 pageToken、count(有效 范围 [1, 100])、order |
callback | IRCIMIWGetFriendApplicationsCallback? | 返回 RCIMIWPagingQueryResult<RCIMIWFriendApplicationInfo> |
好友请求有效期为 7 天,服务端最多保存最近 7 天的数据。分页拉取时,首页 pageToken 置空,从第二页开始使用上一页返回的 pageToken,当返回值为空字符串时代表没有更多数据。
示例代码
final RCIMIWPagingQueryOption option = RCIMIWPagingQueryOption.create(
pageToken: '',
count: 20,
order: false,
);
final IRCIMIWGetFriendApplicationsCallback callback = IRCIMIWGetFriendApplicationsCallback(
onSuccess: (RCIMIWPagingQueryResult<RCIMIWFriendApplicationInfo>? page) {
debugPrint('getFriendApplications => ${page?.records.length}');
final String? nextPageToken = page?.pageToken;
// 根据 pageToken 再次调用以继续拉取
},
onError: (int? code) => debugPrint('getFriendApplications failed => $code'),
);
await IMEngineManager().engine?.getFriendApplications(
<RCIMIWFriendApplicationType>[RCIMIWFriendApplicationType.sent, RCIMIWFriendApplicationType.received],
<RCIMIWFriendApplicationStatus>[
RCIMIWFriendApplicationStatus.unhandled,
RCIMIWFriendApplicationStatus.accepted,
RCIMIWFriendApplicationStatus.refused,
],
option,
callback: callback,
);
同意加为好友
接口
acceptFriendApplication(
String userId,
{IRCIMIWOperationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userId | String | 申请者 ID |
callback | IRCIMIWOperationCallback? | 接受成功 / 失败通知 |
示例代码
final IRCIMIWOperationCallback callback = IRCIMIWOperationCallback(
onSuccess: () => debugPrint('acceptFriendApplication success'),
onError: (int? code) => debugPrint('acceptFriendApplication failed => $code'),
);
await IMEngineManager().engine?.acceptFriendApplication(
'user1',
callback: callback,
);
接受成功后,双方触发 onFriendAdded,对应申请的 FriendApplicationStatus 变为 accepted。
拒绝加为好友
接口
refuseFriendApplication(
String userId,
{IRCIMIWOperationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userId | String | 申请者 ID |
callback | IRCIMIWOperationCallback? | 拒绝成功 / 失败通知 |
示例代码
await IMEngineManager().engine?.refuseFriendApplication(
'user1',
callback: IRCIMIWOperationCallback(
onSuccess: () => debugPrint('refuse success'),
onError: (int? code) => debugPrint('refuse failed => $code'),
),
);
拒绝后,双方会触发 onFriendApplicationStatusChanged,状态为 RCIMIWFriendApplicationStatus.refused。
好友信息的设置与获取
获取好友列表
接口
getFriends(
RCIMIWFriendType friendType,
{IRCIMIWGetFriendsCallback? callback}
)
参数 说明
| 参数 | 类型 | 说明 |
|---|---|---|
friendType | RCIMIWFriendType | 查询的好友方向(仅 both) |
callback | IRCIMIWGetFriendsCallback? | 返回 List<RCIMIWFriendInfo> |
示例代码
await IMEngineManager().engine?.getFriends(
RCIMIWFriendType.both,
callback: IRCIMIWGetFriendsCallback(
onSuccess: (List<RCIMIWFriendInfo>? infos) => debugPrint('friend count=${infos?.length ?? 0}'),
onError: (int? code) => debugPrint('getFriends failed => $code'),
),
);
好友信息设置
接口
setFriendInfo(
RCIMIWFriendInfo friendInfo,
{IRCIMIWSetFriendInfoCallback? callback}
)
RCIMIWFriendInfo 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
userId | String | 必填,好友用户 ID |
remark | String? | 备注名,最长 64 个字符,传空字符串可清除 |
extFields | Map<String, dynamic>? | 自定义属性 Map,最多 10 个 key,需先在控制台 好友自定义属性 中配置 |
如开启信息托管审核,可在融云控制台 IM 服务 > 功能配置 > 安全&审核 > IM 信息托管审核 中设置需要审核的字段。
示例代码
final RCIMIWFriendInfo friendInfo = RCIMIWFriendInfo.create(
userId: 'user1',
remark: 'user1 的备注',
extFields: <String, dynamic>{'ext_key_1': 'value'},
);
await IMEngineManager().engine?.setFriendInfo(
friendInfo,
callback: IRCIMIWSetFriendInfoCallback(
onSuccess: () => debugPrint('setFriendInfo success'),
onError: (int? code, List<String>? errorKeys) => debugPrint('setFriendInfo failed => $code $errorKeys'),
),
);
根据用户 ID 获取好友信息
接口
getFriendsInfo(
List<String> userIds,
{IRCIMIWGetFriendsInfoCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
userIds | List<String> | 需要查询的好友 ID,最多 100 个 |
callback | IRCIMIWGetFriendsInfoCallback? | 返回 List<RCIMIWFriendInfo> |
示例代码
await IMEngineManager().engine?.getFriendsInfo(
<String>['user1', 'user2'],
callback: IRCIMIWGetFriendsInfoCallback(
onSuccess: (List<RCIMIWFriendInfo>? infos) => debugPrint('infos => ${infos?.map((e) => e.toJson())}'),
onError: (int? code) => debugPrint('getFriendsInfo failed => $code'),
),
);
根据好友昵称搜索好友信息
接口
searchFriendsInfo(
String keyword,
{IRCIMIWSearchFriendsInfoCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
keyword | String | 搜索关键字,先匹配备注,再匹配昵称,长度 ≤ 64 |
callback | IRCIMIWSearchFriendsInfoCallback? | 返回命中的 List<RCIMIWFriendInfo> |
示例代码
await IMEngineManager().engine?.searchFriendsInfo(
'张三',
callback: IRCIMIWSearchFriendsInfoCallback(
onSuccess: (List<RCIMIWFriendInfo>? infos) => debugPrint('search result => ${infos?.length ?? 0}'),
onError: (int? code) => debugPrint('searchFriendsInfo failed => $code'),
),
);