tencent cloud

Feedback

Android&iOS&Windows&Mac

Last updated: 2023-07-17 15:38:05

    Overview

    The group management feature allows creating a group, joining a group, getting the joined groups, leaving a group, or disbanding a group through methods in the V2TIMGroupManager(Android) / V2TIMManager(Group)(iOS and macOS) core class.

    Group Event Listener

    In the group management feature as described below, the IM 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 IM console to check or configure the group system notification 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);

    Creating a Group

    Ordinary 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.
    Caution
    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 a group

    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);

    Joining a group by invitation

    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);

    Joining a group on request and on approval

    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&)