Manage Group

Overview

The group management feature allows creating a group, joining a group, getting the joined groups, leaving a group, or disbanding a group.

Group Event Listener

In the group management feature as described below, the SDK will automatically trigger the group event notification callback, for example, when someone joins or leaves a group.
Call addGroupListener (Android / iOS and macOS / Windows) to add a group event listener.
Group events are defined in V2TIMGroupListener (Android / iOS and macOS / Windows), including group member notification, group lifecycle notification, group join request notification, and topic event listening callback.
To stop receiving group events, call removeGroupListener (Android / iOS and macOS / Windows) to remove the group event listener.
If you have configured a group event listener but don't receive events as expected, you can log in to the Console to check Group system notification configuration, Configation page is as follows:



Caution
Audio-video groups don't support configuring the notifications of group member change and group profile change.
Sample code:
Android
iOS and macOS
Windows
V2TIMGroupListener groupListener = new V2TIMGroupListener() {
// Group member notification, group lifecycle notification, group join request notification, topic event listening callback, etc.
@Override
public void onMemberEnter(String groupID, List<V2TIMGroupMemberInfo> memberList) {
// A member joined the group. All the group members can receive the notification.
}
@Override
void onMemberLeave(String groupID, V2TIMGroupMemberInfo member) {
// A member left the group. All the group members can receive the notification.
}

@Override
public void onReceiveRESTCustomData(String groupID, byte[] customData) {
// Custom system notification sent by the server
}
};

V2TIMManager.getInstance().addGroupListener(groupListener);
[[V2TIMManager sharedInstance] addGroupListener:self];

// Group member notification, group lifecycle notification, group join request notification, topic event listening callback, etc.
- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {
// A member joined the group. All the group members can receive the notification.
}

- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member {
// A member left the group. All the group members can receive the notification.
}

- (void)onReceiveRESTCustomData:(NSString *)groupID data:(NSData *)data {
// Custom system notification sent by the server
}
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

// Group member notification, group lifecycle notification, group join request notification, topic event listening callback, etc.

void OnMemberEnter(const V2TIMString& groupID, const V2TIMGroupMemberInfoVector& memberList) override {
// A member joined the group. All the group members can receive the notification.
}

void OnMemberLeave(const V2TIMString& groupID, const V2TIMGroupMemberInfo& member) override {
// A member left the group. All the group members can receive the notification.
}

void OnReceiveRESTCustomData(const V2TIMString& groupID, const V2TIMBuffer& customData) override {
// Custom system notification sent by the server
}
};

// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Search Groups

You can only search for groups that have been stored locally, such as the list of joined groups and group profiles that have been pulled.
You can call the searchGroups (Android/iOS & Mac/Windows) API to search local groups. You can set the search keyword keywordList, and specify the search range, that is, whether to search the userID,groupName fields.
Note:
The local group search feature is only supported by v5.4.666 and later.
The local group search is an advanced feature, Purchase Advanced Edition to use.
Search keyword list, up to 5 supported.
The example code is as follows:
Android
iOS & Mac
Windows
V2TIMGroupSearchParam searchParam = new V2TIMGroupSearchParam();
searchParam.setKeywordList(Arrays.asList("keyword1", "keyword2", "keyword3")); // Set the search keyword list, up to 5 supported.
searchParam.setSearchGroupID(true); // Set whether to search for Group ID
searchParam.setSearchGroupName(true); // Set whether to search for Group Name
V2TIMManager.getGroupManager().searchGroups(searchParam, new V2TIMValueCallback<List<V2TIMGroupInfo>>() {
@Override
public void onSuccess(List<V2TIMGroupInfo> groupInfoList) {
// Search group information successful
}

@Override
public void onError(int code, String desc) {
// Search group information failed
}
});
V2TIMGroupSearchParam *searchParam = [[V2TIMGroupSearchParam alloc] init];
searchParam.keywordList = @[@"keyword1", @"keyword2", @"keyword3"];
searchParam.isSearchGroupID = true;
searchParam.isSearchGroupName = true;
// Search group information
[[V2TIMManager sharedInstance] searchGroups:searchParam succ:^(NSArray<V2TIMGroupInfo *> *groupList) {
// Search group information successful
} fail:^(int code, NSString *desc) {
// Search group information failed
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMGroupSearchParam searchParam;
searchParam.keywordList = keywordList;
searchParam.isSearchGroupID = true;
searchParam.isSearchGroupName = true;

auto callback = new ValueCallback<V2TIMGroupInfoVector>{};
callback->SetCallback(
[=](const V2TIMGroupInfoVector& groupInfoList) {
// Search group succeeded
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Search group failed
delete callback;
});

V2TIMManager::GetInstance()->GetGroupManager()->SearchGroups(searchParam, callback);

Creating a Group

Basic API

Call the createGroup ordinary API (Android / iOS and macOS / Windows) and specify parameters to create a group.
The createGroup parameters are as described below:
Parameter
Definition
Required
Description
groupType
Group type
Yes
For more information, see Group Types.
groupID
Group ID
No
If it is left empty, an ID will be automatically assigned after a group is created successfully.
It can be customized as instructed in Custom Group IDs.
groupName
Group name
Yes
It can contain up to 30 bytes.
If you have called addGroupListener to add a group event listener as instructed in Group Event Listener, onGroupCreated (Android / iOS and macOS / Windows) will be called back after a group is created successfully.
Sample code:
Android
iOS and macOS
Windows
V2TIMManager.getInstance().createGroup(V2TIMManager.GROUP_TYPE_WORK, null, "groupA", new V2TIMValueCallback<String>() {
@Override
public void onSuccess(String s) {
// Group created successfully
}

@Override
public void onError(int code, String desc) {
// Failed to create the group
}
});
// Listen for the group creation notification
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onGroupCreated(String groupID) {
// A group was created. `groupID` is the ID of the created group.
}
});
// Create a group
[[V2TIMManager sharedInstance] createGroup:GroupType_Work groupID:nil groupName:@"groupA" succ:^(NSString *groupID) {
// Group created successfully
} fail:^(int code, NSString *desc) {
// Failed to create the group
}];

// Listen for the group creation notification
[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onGroupCreated:(NSString *)groupID {
// A group was created. `groupID` is the ID of the created group.
}
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

auto callback = new ValueCallback<V2TIMString>{};
callback->SetCallback(
[=](const V2TIMString& string) {
// Group created successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to create the group
delete callback;
});

V2TIMManager::GetInstance()->CreateGroup("Work", {}, "groupA", callback);

// Listen for the group creation notification
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnGroupCreated(const V2TIMString& groupID) override {
// A group was created. `groupID` is the ID of the created group.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Advanced API

To initialize the group information such as group introduction, group profile photo, and existing group members when creating a group, call the createGroup advanced API (Android / iOS and macOS / Windows), and the groupID will be returned in the callback for successful creation.
Sample code:
Android
iOS and macOS
Windows
// Use the `createGroup` advanced API to create a work group
V2TIMGroupInfo v2TIMGroupInfo = new V2TIMGroupInfo();
v2TIMGroupInfo.setGroupName("testWork");
v2TIMGroupInfo.setGroupType("Work");
v2TIMGroupInfo.setIntroduction("this is a test Work group");

List<V2TIMCreateGroupMemberInfo> memberInfoList = new ArrayList<>();
V2TIMCreateGroupMemberInfo memberA = new V2TIMCreateGroupMemberInfo();
memberA.setUserID("vinson");
V2TIMCreateGroupMemberInfo memberB = new V2TIMCreateGroupMemberInfo();
memberB.setUserID("park");
memberInfoList.add(memberA);
memberInfoList.add(memberB);

V2TIMManager.getGroupManager().createGroup(
v2TIMGroupInfo, memberInfoList, new V2TIMValueCallback<String>() {
@Override
public void onError(int code, String desc) {
// Creation failed
}
@Override
public void onSuccess(String groupID) {
// Group created successfully
}
});
// Use the `createGroup` advanced API to create a work group
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupName = @"testWork";
info.groupType = @"Work";
NSMutableArray *memberList = [NSMutableArray array];
V2TIMCreateGroupMemberInfo *memberInfo = [[V2TIMCreateGroupMemberInfo alloc] init];
memberInfo.userID = @"vinson";
[memberList addObject:memberInfo];
[[V2TIMManager sharedInstance] createGroup:info memberList:memberList succ:^(NSString *groupID) {
// Group created successfully
} fail:^(int code, NSString *msg) {
// Failed to create the group
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// Use the `createGroup` advanced API to create a work group
V2TIMGroupInfo info;
info.groupType = "Work";
info.groupName = "testWork";
info.introduction = "this is a test Work group";

V2TIMCreateGroupMemberInfoVector memberInfoList;
V2TIMCreateGroupMemberInfo memberInfo1;
memberInfo1.userID = "vinson";
memberInfoList.PushBack(memberInfo1);
V2TIMCreateGroupMemberInfo memberInfo2;
memberInfo2.userID = "park";
memberInfoList.PushBack(memberInfo2);

auto callback = new ValueCallback<V2TIMString>{};
callback->SetCallback(
[=](const V2TIMString& string) {
// Group created successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Creation failed
delete callback;
});

V2TIMManager::GetInstance()->GetGroupManager()->CreateGroup(info, memberInfoList, callback);

Joining a Group

The method for joining a group may vary by group type as follows:
Type
Method for Joining a Group
Work group (Work)
By invitation
Public group (Public)
On request from the user and on approval from the group owner or admin
Meeting group (Meeting)
Free to join
Community (Community)
Free to join
Audio-video group (AVChatRoom)
Free to join
The following describes how to join the groups in an easy-to-hard sequence.
Note:
You need to call addGroupListener to add a group event listener in advance as instructed in Group Event Listener to receive the following group events.

Free to Join

Meeting groups (Meeting), audio-video groups (AVChatRoom), and communities are mainly used for free interaction scenarios, such as online meeting and live show. The process of joining such groups is the simplest:
1. The user calls joinGroup (Android / iOS and macOS / Windows) to join the group.
2. After the user has successfully joined the group, all the group members (including the user) will receive the onMemberEnter callback (Android / iOS and macOS / Windows).
Note:
Work group does not support free group joining a group by default, you can modify the groupAddOpt field of V2TIMGroupInfo by calling setGroupInfo (Android / iOS & Mac / Windows) to enable free group joining.
Sample code:
Android
iOS and macOS
Windows
// Join a group
V2TIMManager.getInstance().joinGroup("groupA", "it's me!", new V2TIMCallback() {
@Override
public void onSuccess() {
// Joined the group successfully
}

@Override
public void onError(int code, String desc) {
// Failed to join the group
}
});

// Listen for the group join event
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberEnter(String groupID, List<V2TIMGroupMemberInfo> memberList) {
// A user joined the group.
}
});

// Join a group
[[V2TIMManager sharedInstance] joinGroup:@"groupA" msg:@"it's me!" succ:^{
// Joined the group successfully
} fail:^(int code, NSString *desc) {
// Failed to join the group
}];

// Listen for the group join event
[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {
// A user joined the group.
}
class Callback final : public V2TIMCallback {
public:
using SuccessCallback = std::function<void()>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

Callback() = default;
~Callback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess() override {
if (success_callback_) {
success_callback_();
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

auto callback = new Callback{};
callback->SetCallback(
[=]() {
// Joined the group successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to join the group
delete callback;
});

V2TIMManager::GetInstance()->JoinGroup("groupA", "it's me!", callback);

// Listen for the group join event
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnMemberEnter(const V2TIMString& groupID, const V2TIMGroupMemberInfoVector& memberList) override {
// A user joined the group.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Invite to Join

Work groups (Work) are suitable for communication in work environments. The interaction pattern is designed to disable proactive group joining and only allow users to be invited to join the group by group members. The steps to join a group are as follows:
1. A group member calls inviteUserToGroup (Android / iOS and macOS / Windows) to invite a user to the group.
2. All the group members (including the inviter) receive the onMemberInvited callback (Android / iOS and macOS / Windows), which can contain some UI tips.
Note:
1. Since v7.1, other group types except work group (Work) do not support joining a group by invitation by default, you can modify the groupApproveOpt field of V2TIMGroupInfo by calling setGroupInfo (Android / iOS & Mac / Windows) to open joining a group by invitation.
2. AVChatRoom group, community, and topic do not allow joining a group by invitation by default, and do not support modification.
Sample code:
Android
iOS and macOS
Windows
// Invite the `userA` user to join the `groupA` group
List<String> userIDList = new ArrayList<>();
userIDList.add("userA");
V2TIMManager.getGroupManager().inviteUserToGroup("groupA", userIDList, new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {
@Override
public void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {
// Invited the user to the group successfully
}

@Override
public void onError(int code, String desc) {
// Failed to invite the user to the group
}
});

// Listen for the group invitation event
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberInvited(String groupID, V2TIMGroupMemberInfo opUser, List<V2TIMGroupMemberInfo> memberList) {
// A user was invited to the group. This callback can contain some UI tips.
}
});
// Invite the `userA` user to join the `groupA` group
[[V2TIMManager sharedInstance] inviteUserToGroup:@"groupA" userList:@[@"userA"] succ:^(NSArray<V2TIMGroupMemberOperationResult *> *resultList) {
// Invited the user to the group successfully
} fail:^(int code, NSString *desc) {
// Failed to invite the user to the group
}];

// Listen for the group invitation event
[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onMemberInvited:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {
// This callback can contain some UI tips.
}
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// Invite the `userA` user to join the `groupA` group
V2TIMStringVector userList;
userList.PushBack("userA");

auto callback = new ValueCallback<V2TIMGroupMemberOperationResultVector>{};
callback->SetCallback(
[=](const V2TIMGroupMemberOperationResultVector& groupMemberOperationResultList) {
// Invited the user to the group successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to invite the user to the group
delete callback;
});

V2TIMManager::GetInstance()->GetGroupManager()->InviteUserToGroup("groupA", userList, callback);

// Listen for the group invitation event
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnMemberInvited(const V2TIMString& groupID, const V2TIMGroupMemberInfo& opUser,
const V2TIMGroupMemberInfoVector& memberList) override {
// A user was invited to the group. This callback can contain some UI tips.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Invite and Approve to Join

A public group (Public) is similar to the interest group and clan group of QQ. Anyone can join it on request and on approval from the group owner or admin.
The steps to join a group on request and on approval are as follows:


Description of process:
1. The user calls joinGroup (Android / iOS and macOS / Windows) to request to join the group.
2. The group owner or admin receives the onReceiveJoinApplication group join request notification (Android / iOS and macOS / Windows) and calls getGroupApplicationList (Android / iOS and macOS / Windows) to get the group join request list.
3. The group owner or admin traverses the group join request list and calls acceptGroupApplication (Android / iOS and macOS / Windows) to approve a request or refuseGroupApplication (Android / iOS and macOS / Windows) to reject it.
4. After the request to join the group is approved or rejected, the user will receive the onApplicationProcessed callback (Android / iOS and macOS / Windows). Here, if isAgreeJoin is true/YES, the request is approved; otherwise, it is rejected.
5. On approval, all the group members (including the user) will receive the onMemberEnter callback (Android / iOS and macOS / Windows), notifying the group members that someone joined the group.
Sample code:
Android
iOS and macOS
Windows
// ******Group owner******//
// 1. The group owner changes the group join option to approval required.
V2TIMGroupInfo groupInfo = new V2TIMGroupInfo();
groupInfo.setGroupID("groupB");
groupInfo.setGroupAddOpt(V2TIMGroupInfo.V2TIM_GROUP_ADD_AUTH);
V2TIMManager.getGroupManager().setGroupInfo(groupInfo, new V2TIMCallback() {
@Override
public void onSuccess() {
// Changed the group join option successfully
}

@Override
public void onError(int code, String desc) {
// Failed to change the group join option
}
});

// 2. The group owner listens for and processes requests to join the group.
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onReceiveJoinApplication(String groupID, V2TIMGroupMemberInfo member, String opReason) {
V2TIMManager.getGroupManager().getGroupApplicationList(new V2TIMValueCallback<V2TIMGroupApplicationResult>() {
@Override
public void onSuccess(V2TIMGroupApplicationResult v2TIMGroupApplicationResult) {
List<V2TIMGroupApplication> groupApplicationList = v2TIMGroupApplicationResult.getGroupApplicationList();
for (V2TIMGroupApplication application : groupApplicationList) {
if (application.getGroupID().equals(groupID) && application.getFromUser().equals(member.getUserID())) {
// Approve group join
if (agree) {
// Approve the group join request
V2TIMManager.getGroupManager().acceptGroupApplication(application, "agree", new V2TIMCallback() {
@Override
public void onSuccess() {
// Approved the group join request successfully
}

@Override
public void onError(int code, String desc) {
// Failed to approve the group join request
}
});
} else {
// Reject the group join request
V2TIMManager.getGroupManager().refuseGroupApplication(application, "not agree", new V2TIMCallback() {
@Override
public void onSuccess() {
// Rejected the group join request successfully
}

@Override
public void onError(int code, String desc) {
// Failed to reject the group join request
}
});
}
return;
}
}

V2TIMManager.getGroupManager().setGroupApplicationRead(new V2TIMCallback() {
@Override
public void onSuccess() {
// Marked the group join request list as read successfully
}

@Override
public void onError(int code, String desc) {
// Failed to mark the group join request list as read
}
});
}

@Override
public void onError(int code, String desc) {
// Failed to obtain the group join request list
}
});
}
});

// ******User******//
// 1. The user requests to join the group.
V2TIMManager.getInstance().joinGroup("groupB", "it's me!", new V2TIMCallback() {
@Override
public void onSuccess() {
// Joined the group successfully
}

@Override
public void onError(int code, String desc) {
// Failed to join the group
}
});
// 2. The user listens for the request review result.
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onApplicationProcessed(String groupID, V2TIMGroupMemberInfo opUser, boolean isAgreeJoin,
String opReason) {
// The request to join the group is processed.
}

@Override
public void onMemberEnter(String groupID, List<V2TIMGroupMemberInfo> memberList) {
// This callback will be received if the group join request is approved.
}
});
// ******Group owner******//
// 1. The group owner changes the group join option to approval required.
V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init];
info.groupID = @"groupA";
info.groupAddOpt = V2TIM_GROUP_ADD_AUTH;
[[V2TIMManager sharedInstance] setGroupInfo:info succ:^{
// Changed the group join option successfully
} fail:^(int code, NSString *desc) {
// Changed the group join option successfully
}];

// 2. The group owner listens for and processes requests to join the group.
[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onReceiveJoinApplication:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member opReason:(NSString *)opReason {
[[V2TIMManager sharedInstance] getGroupApplicationList:^(V2TIMGroupApplicationResult *result) {
for (V2TIMGroupApplication *application in result.applicationList) {
if ([application.groupID isEqualToString:groupID] && [application.fromUser isEqualToString:member.userID]) {
// Approve group join
[[V2TIMManager sharedInstance] acceptGroupApplication:application reason:@"agree" succ:^{
// Approved the group join request successfully
} fail:^(int code, NSString *desc) {
// Failed to approve the group join request
}];

// Reject group join
[[V2TIMManager sharedInstance] refuseGroupApplication:application reason:@"refuse" succ:^{
// Rejected the group join request successfully
} fail:^(int code, NSString *desc) {
// Failed to reject the group join request
}];

// Mark the request as read
[[V2TIMManager sharedInstance] setGroupApplicationRead:^{
// Marked the group join request list as read successfully
} fail:^(int code, NSString *desc) {
// Failed to mark the group join request list as read
}];
}
}
} fail:^(int code, NSString *desc) {
// Failed to obtain the group join request list
}];
}

// ******Request******//
// 1. The user requests to join the group.
[[V2TIMManager sharedInstance] joinGroup:@"groupA" msg:@"it's me!" succ:^{
// Joined the group successfully
} fail:^(int code, NSString *desc) {
// Failed to join the group
}];

// 2. The user listens for the request review result.
[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onApplicationProcessed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser opResult:(BOOL)isAgreeJoin opReason:(NSString *)opReason {
// The request to join the group is processed.
}
- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList; {
// This callback will be received if the group join request is approved.
}
class Callback final : public V2TIMCallback {
public:
using SuccessCallback = std::function<void()>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

Callback() = default;
~Callback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess() override {
if (success_callback_) {
success_callback_();
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

////////////////////////////////////////////////// Group owner //////////////////////////////////////////////////

// 1. The group owner changes the group join option to approval required.
V2TIMGroupInfo info;
info.groupID = "groupB";
info.groupAddOpt = V2TIMGroupAddOpt::V2TIM_GROUP_ADD_AUTH;
info.modifyFlag = V2TIMGroupInfoModifyFlag::V2TIM_GROUP_INFO_MODIFY_FLAG_GROUP_ADD_OPTION;
auto callback = new Callback;
callback->SetCallback(
[=]() {
// Changed the group join option successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to change the group join option
delete callback;
});
V2TIMManager::GetInstance()->GetGroupManager()->SetGroupInfo(info, callback);

// 2. The group owner listens for and processes requests to join the group.
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnReceiveJoinApplication(const V2TIMString& groupID, const V2TIMGroupMemberInfo& member,
const V2TIMString& opReason) override {
auto callback = new ValueCallback<V2TIMGroupApplicationResult>{};
callback->SetCallback(
[=](const V2TIMGroupApplicationResult& groupApplicationResult) {
const V2TIMGroupApplicationVector& groupApplicationList =
groupApplicationResult.applicationList;
for (size_t i = 0; i < groupApplicationList.Size(); ++i) {
const V2TIMGroupApplication& application = groupApplicationList[i];
if (application.groupID == groupID && application.fromUser == member.userID) {
if (...) { // Approve group join
auto callback = new Callback;
callback->SetCallback(
[=]() {
// Approved the group join request successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to approve the group join request
delete callback;
});
V2TIMManager::GetInstance()->GetGroupManager()->AcceptGroupApplication(
application, "agree", callback);
} else { // Reject group join
auto callback = new Callback;
callback->SetCallback(
[=]() {
// Rejected the group join request successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to reject the group join request
delete callback;
});
V2TIMManager::GetInstance()->GetGroupManager()->RefuseGroupApplication(
application, "refuse", callback);
}
break;
}
}

auto callback = new Callback;
callback->SetCallback(
[=]() {
// Marked the group join request list as read successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to mark the group join request list as read
delete callback;
});
V2TIMManager::GetInstance()->GetGroupManager()->SetGroupApplicationRead(callback);

delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to obtain the group join request list
delete callback;
});

V2TIMManager::GetInstance()->GetGroupManager()->GetGroupApplicationList(callback);
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

////////////////////////////////////////////////// User //////////////////////////////////////////////////

// 1. The user requests to join the group.
auto callback = new Callback{};
callback->SetCallback(
[=]() {
// Joined the group successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to join the group
delete callback;
});
V2TIMManager::GetInstance()->JoinGroup("groupB", "it's me!", callback);

// 2. The user listens for the request review result.
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnApplicationProcessed(const V2TIMString& groupID, const V2TIMGroupMemberInfo& opUser,
bool isAgreeJoin, const V2TIMString& opReason) override {
// The request to join the group is processed.
}
void OnMemberEnter(const V2TIMString& groupID, const V2TIMGroupMemberInfoVector& memberList) override {
// This callback will be received if the group join request is approved.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);
The group owner or admin can also call the setGroupInfo API (Android / iOS and macOS / Windows) to change the group join option (groupAddOpt) and approval option (groupApproveOpt) to "no group join allowed" or "no approval required".
V2TIMGroupAddOpt has the following options:
Group Join Option
Description
V2TIM_GROUP_ADD_FORBID
No users can join the group.
V2TIM_GROUP_ADD_AUTH
Approval from the group owner or admin is required to join the group (default value).
V2TIM_GROUP_ADD_ANY
Any user can join the group without approval.

Getting the Joined Groups

Call getJoinedGroupList (Android / iOS and macOS / Windows) to get the list of joined work groups (Work), public groups (Public), meeting groups (Meeting), and communities (Community, which don't support the topic feature). Audio-video groups (AVChatRoom) and communities (Community, which support the topic feature) are not included in this list.
Sample code:
Android
iOS and macOS
Windows
V2TIMManager.getGroupManager().getJoinedGroupList(new V2TIMValueCallback<List<V2TIMGroupInfo>>() {
@Override
public void onSuccess(List<V2TIMGroupInfo> v2TIMGroupInfos) {
// Obtained the list of joined groups successfully
}

@Override
public void onError(int code, String desc) {
// Failed to obtain the list of joined groups
}
});
[[V2TIMManager sharedInstance] getJoinedGroupList:^(NSArray<V2TIMGroupInfo *> *groupList) {
// Obtained the list of joined groups successfully
} fail:^(int code, NSString *desc) {
// Failed to obtain the list of joined groups
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

auto callback = new ValueCallback<V2TIMGroupInfoVector>{};
callback->SetCallback(
[=](const V2TIMGroupInfoVector& groupInfoList) {
// Obtained the list of joined groups successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to obtain the list of joined groups
delete callback;
});

V2TIMManager::GetInstance()->GetGroupManager()->GetJoinedGroupList(callback);

Leaving a Group

Call quitGroup (Android / iOS and macOS / Windows) to leave a group. The member who left the group will receive the onQuitFromGroup callback (Android / iOS and macOS / Windows). Other group members will receive the onMemberLeave callback (Android / iOS and macOS / Windows).
Caution
The group owner cannot leave a public group (Public), meeting group (Meeting), community, or audio-video group (AVChatRoom) and can only disband it.
Sample code:
Android
iOS and macOS
Windows
V2TIMManager.getInstance().quitGroup("groupA", new V2TIMCallback() {
@Override
public void onSuccess() {
// Left the group successfully
}

@Override
public void onError(int code, String desc) {
// Failed to leave the group
}
});

V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberLeave(String groupID, V2TIMGroupMemberInfo member) {
// A group member left the group.
}
});
[[V2TIMManager sharedInstance] quitGroup:@"groupA" succ:^{
// Left the group successfully
} fail:^(int code, NSString *desc) {
// Failed to leave the group
}];

[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member {
// A group member left the group.
}
class Callback final : public V2TIMCallback {
public:
using SuccessCallback = std::function<void()>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

Callback() = default;
~Callback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess() override {
if (success_callback_) {
success_callback_();
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

auto callback = new Callback{};
callback->SetCallback(
[=]() {
// Left the group successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to leave the group
delete callback;
});
V2TIMManager::GetInstance()->QuitGroup("groupA", callback);

// Listen for the notification of group member leaving
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnMemberLeave(const V2TIMString& groupID, const V2TIMGroupMemberInfo& member) override {
// A group member left the group.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Dismissing Groups

Call dismissGroup (Android / iOS and macOS / Windows) to dismiss a group, and all the group members will receive the onGroupDismissed callback (Android / iOS and macOS / Windows).
If you have allowed automatically disbanding an inactive group on the server, when the group is automatically disbanded by the server, the SDK will receive the onGroupRecycled callback (Android / iOS and macOS / Windows).
Sample code:
Android
iOS and macOS
Windows
V2TIMManager.getInstance().dismissGroup("groupA", new V2TIMCallback() {
@Override
public void onSuccess() {
// Disbanded the group successfully
}

@Override
public void onError(int code, String desc) {
// Failed to disband the group
}
});

V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onGroupDismissed(String groupID, V2TIMGroupMemberInfo opUser) {
// The group was disbanded.
}

@Override
public void onGroupRecycled(String groupID, V2TIMGroupMemberInfo opUser) {
// The group was reclaimed.
}
});
[[V2TIMManager sharedInstance] dismissGroup:@"groupA" succ:^{
// Disbanded the group successfully
} fail:^(int code, NSString *desc) {
// Failed to disband the group
}];

[[V2TIMManager sharedInstance] addGroupListener:self];
- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {
// The group was disbanded.
}

- (void)onGroupRecycled:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {
// The group was reclaimed.
}
class Callback final : public V2TIMCallback {
public:
using SuccessCallback = std::function<void()>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

Callback() = default;
~Callback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess() override {
if (success_callback_) {
success_callback_();
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

auto callback = new Callback{};
callback->SetCallback(
[=]() {
// Disbanded the group successfully
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// Failed to disband the group
delete callback;
});
V2TIMManager::GetInstance()->DismissGroup("groupA", callback);

// Listen for the group disbanding/reclaiming notification
class GroupListener final : public V2TIMGroupListener {
public:
GroupListener() = default;
~GroupListener() override = default;

void OnGroupDismissed(const V2TIMString& groupID, const V2TIMGroupMemberInfo& opUser) override {
// The group was disbanded.
}
void OnGroupRecycled(const V2TIMString& groupID, const V2TIMGroupMemberInfo& opUser) override {
// The group was reclaimed.
}
// Other members …
};
// Add a group event listener. Keep `groupListener` valid before the listener is removed to ensure event callbacks are received.
GroupListener groupListener;
V2TIMManager::GetInstance()->AddGroupListener(&groupListener);

Receiving a Custom Group System Notification

If you call the RESTful API on the server to send custom system messages to the group, the SDK will call back onReceiveRESTCustomData (Android / iOS and macOS / Windows) and return the custom data you send.