Android
Group Channel

Group Channel

A group channel is a chat that provides close interactions among limited number of users. It can be private or public. A private group channel can let a user join the chat through an invitation by another user who is already a member of the chatroom. For 1-on-1 messaging, you can create a private group channel with two members. A public group chat can let a user join the chat without invitation from others. A group channel can consist of one to one hundred members by default setting. This default number of members can increase per request.

A user can receive all messages from the group channels that they are a member of, and sends a message to those channels. They can also receive push notifications, typing indicators, unread counts and read receipts from the joined channels when they go offline. For more information, see the Push Notifications page which describes how to turn on and manage the push preference.


Choose a type of a channel

With our Android SDK, you can use a variety of behaviour related properties when creating different types of group channels. You can create a group channel after configuring these properties.

Private vs. Public

A private group channel (default setting) can be accessed only by users that have accepted an invitation from an existing member of that group. On the other hand, a public group channel can be accessed by any user without an invitation, like an open channel.

Ephemeral vs. Persistent

Messages sent in an ephemeral group channel are not saved in the database of the SendBird system. Therefore, the old messages that scroll up beyond the user's display due to new messages can't be retrieved. On the other hand, messages sent in a persistent group channel (default setting) are stored permanently in the database.

1-on-1 vs. 1-on-N

A distinct group channel can be reused for the same users. If a user is invited as a new member, or if a member leaves the channel, then the distinct property is disabled automatically. For example, when attempting to create a new group channel with 3 users, A, B, and C, if a channel with same users already exists, a reference to the existing channel is just returned to who has attempted the new channel.

Consequently, we recommend that you turn on the distinct property in 1-on-1 messaging channels to reuse the existing channel when a user directly sends a message to another user. If the property is turned off, a new group channel is created with the same user even if there is a previous chat between them, and you can't see the old messages or data.


Create a channel

A user can create a group channel from inviting other users anytime in their client app. At the implemention level, you just need to write your code which passes the IDs of users to invite as a parameter to the creation method.

Before you write the code for creating a group channel for a typical 1-on-1 chat, you should make sure that you turn on the distinct property of the channel. Otherwise, if you turn off the distinct property, a new channel will be created with the same partner user even if there is already an existing channel between them. In this case, multiple 1-on-1 channels between the same two users can exist, each with its own chat history and data.

Note: If you want to retrieve a list of group channels, which also includes the current user's empty channels without any chat, you should set the includeEmptyChannel option to true through the setIncludeEmptyChannel() method of a GroupChannelListQuery instance for the retrieval.

Light Color Skin
Copy
GroupChannel.createChannelWithUserIds(USER_IDS, IS_DISTINCT, new GroupChannel.GroupChannelCreateHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

When creating a channel, you can also append additioanl information like cover image and description by specifying several arguments.

Light Color Skin
Copy
GroupChannel.createChannel(USERS, IS_DISTINCT, NAME, COVER_IMAGE_OR_URL, DATA, CUSTOM_TYPE, HANDLER);
ParameterTypeDescription

USERS

list

Specifies a list of one or more users to invite to the channel.

IS_DISTINCT

boolean

Determines whether to reuse the existing channel instead of creating a new channel with the same users.

NAME

string

Specifies the channel topic, or the name of the channel.

COVER_IMAGE_OR_URL

object

Specifies the cover image URL of the channel, or uploads a file for the cover image.

DATA

string

Specifies additional data that you can store for the channel.

CUSTOM_TYPE

string

Specifies the custom channel type which is used for channel grouping.

HANDLER

interface

Specifies the GroupChannelCreateHandler interface which contains the onResult() callback to receive the response from SendBird server for a channel creation request.

Using the getCoverUrl() and updateChannel() methods, you can get and update the cover image URL of a channel.

Note: You can also create a group channel using the Platform API which helps you control channel creations and member invitations on your server-side.

Otherwise, you can configure GroupChannelParams and create a new channel with that like below.

Light Color Skin
Copy
List<String> users = new ArrayList<>();
users.add("John");
users.add("Harry");
users.add("Jay");

List<String> operators = new ArrayList<>();
operators.add("Jeff");

GroupChannelParams params = new GroupChannelParams()
        .setPublic(false)
        .setEphemeral(false)
        .setDistinct(false)
        .addUserIds(users)
        .setOperatorUserIds(operators)  // Or .setOperators(List<User> operators)
        .setName(NAME)
        .setChannelUrl(UNIQUE_CHANNEL_URL)  // In a group channel, you can create a new channel by specifying its unique channel URL in a 'GroupChannelParams' object.
        .setCoverImage(FILE)            // Or .setCoverUrl(COVER_URL)
        .setData(DATA)
        .setCustomType(CUSTOM_TYPE);

GroupChannel.createChannel(params, new GroupChannel.GroupChannelCreateHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Invite users as members

Only members of a group channel can invite new users into the channel. You can also determine whether the newly invited user sees the past messages in the channel or not.

Note: In your dashboard, go to the Settings > Application > Messages tab, and there is the Chat history option. If the option is turned on, new users can view all messages sent before they have joined the channel. If turned off, new users only see messages sent after they have been invited. By default, this option is turned on.

Light Color Skin
Copy
List<String> userIds = new ArrayList<>();
userIds.add("Tyler");
userIds.add("Young");

groupChannel.inviteWithUserIds(userIds, new GroupChannel.GroupChannelInviteHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Accept or decline an invitation from another user

A user who is invited to a group channel can accept or decline the invitation. If a user accepts an invitation, they join the channel as a new member and can start chatting with other members. If a user declines an invitation, the invitation is canceled.

Light Color Skin
Copy
// Accepting an invitation 
groupChannel.acceptInvitation(new GroupChannel.GroupChannelAcceptInvitationHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

// Declining an invitation 
groupChannel.declineInvitation(new GroupChannel.GroupChannelDeclineInvitationHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

By implementing the onUserReceivedInvitation() and onUserDelclinedInvitation() of a channel event handler, you can make the client apps of other members in the foreground to be notified of the results of two actions above. For more information, see the Event Handler page.

Note: Using the setChannelInvitationPreference(), you can determine for users within an application whether or not to automatically join a private group channel promptly from an invitation without having to accept it. By default, the value of channel invitation preference is true. If you want to give them the ability to decide whether to accept or decline an invitation, you should set the preference's value to false via the setChannelInvitationPreference() like the following sample code.

Light Color Skin
Copy
boolean autoAccept = false; // The value of `true` (default) means that a user will automatically join a group channel with no choice of accepting and declining an invitation. 

SendBird.setChannelInvitationPreference(autoAccept, new SendBird.SetChannelInvitationPreferenceHandler() {
    @Override
    public void onResult(SendBirdException e) {
            if (e != null) {    // Error.
                return;
        }
    }
});

Join a channel as a member

This is only for public group channels. Any user can join a public group channel as a member without an invitation and chat with other members in the channel.

Light Color Skin
Copy
if (groupChannel.isPublic()) {
    groupChannel.join(new GroupChannel.GroupChannelJoinHandler() {
        @Override
        public void onResult(SendBirdException e) {
            if (e != null) {    // Error.
                return;
            }
        }
    });
}

Leave a channel

If a user leaves a group channel, the user can't receive messages from the channel anymore.

Light Color Skin
Copy
groupChannel.leave(new GroupChannel.GroupChannelLeaveHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Freeze and unfreeze a channel

You can temporarily disable various functions of a group channel to stop members from chatting in the channel, and enable the functions so that the members chat with each other. Note that in a frozen channel, normal members can't chat each other but the operators can send a message to the channel.

Light Color Skin
Copy
// Freezing a channel
groupChannel.freeze(new GroupChannel.GroupChannelFreezeHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {        // Error.
            return;
        }

        // TODO: Custom implementation for what should be done after freezing.
    }
});

// Unfreezing a channel
groupChannel.unfreeze(new GroupChannel.GroupChannelUnfreezeHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {        // Error.
            return;
        }

        // TODO: Custom implementation for what should be done after unfreezing.
    }
});

Retrieve a list of channels

You can get a list of the current user's group channels using the next() method of a GroupChannelListQuery instance which returns a list of GroupChannel objects.

Note: Using the setIncludeEmpty() method of a GroupChannelListQuery instance, you can determine whether or not to include empty channels in the result. The empty channels indicate group channels that have been created but currently contain no messages. By default, empty channels are not included (not displayed).

Light Color Skin
Copy
GroupChannelListQuery channelListQuery = GroupChannel.createMyGroupChannelListQuery();
channelListQuery.setIncludeEmpty(true);
channelListQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Retrieve a channel by URL

Since a channel URL is a unique identifier of a group channel, you can use a URL when retrieving a channel object.

Light Color Skin
Copy
GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GroupChannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }

    // TODO: Implement what is needed with the contents of the response in the groupChannel parameter.
    }
});

Note: We recommend that you store a user's channel URLs to handle the lifecycle or state changes of your client app, or other unexpected situations. For example, when a user is disconnected from SendBird server due to switching to another app temporarily, you can provide a smooth restoration of the user's state using a stored URL to fetch the appropriate channel instance.


Hide or archive a channel from a list of channels

The following code will allow you to hide or archive a specific group channel from a list of the channels.

Light Color Skin
Copy
groupChannel.hide(IS_HIDE_PREVIOUS_MESSAGES, IS_ALLOW_AUTO_UNHIDE, new GroupChannel.GroupChannelHideHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

groupChannel.unhide(new GroupChannel.GroupChannelUnhideHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {        // Error.
            return;
        }
    }
});
ParameterTypeDescription

IS_HIDE_PREVIOUS_MESSAGES

boolean

When the channel gets appeared back in the list, determines whether to conceal the messages sent and received before hiding or archiving the channel. If set to true, the previous messages aren't displayed in the channel. (Default: false)

IS_ALLOW_AUTO_UNHIDE

boolean

Determines the state and operating behavior of the channel in the list. If set to true, the channel is hidden from the list, automatically gets unhidden when receiving a new message from other members of the channel, and appears back. If set to false, the channel is archived and disappeared from the list, and never appears back unless the unhide() is called for unarchiving. (Default: true)

Using the getHiddenState(), you can check the channel state with regard to the list.

Light Color Skin
Copy
if (groupChannel.getHiddenState() == GroupChannel.HiddenState.UNHIDDEN) {   
    // The channel is displayed in the list.
} else if (groupChannel.getHiddenState() == GroupChannel.HiddenState.HIDDEN_ALLOW_AUTO_UNHIDE) {
    // The channel is hidden from the list, and get appeared back on condition.
} else if (groupChannel.getHiddenState() == GroupChannel.HiddenState.HIDDEN_PREVENT_AUTO_UNHIDE) {  
    // The channel is archived, and get appeared back in the list only when the unhide() is called. 
}

You can also filter channels by their state like the following:

Light Color Skin
Copy
GroupChannelListQuery filteredQuery = GroupChannel.createMyGroupChannelListQuery();

filteredQuery.setIncludeEmpty(true);
filteredQuery.setHiddenChannelFilter(GroupChannelListQuery.HiddenChannelFilter.HIDDEN_PREVENT_AUTO_UNHIDE);
// The filter options are limited to `UNHIDDEN`, `HIDDEN`, `HIDDEN_ALLOW_AUTO_UNHIDE`, or `HIDDEN_PREVENT_AUTO_UNHIDE`.
// If set to `HIDDEN`, hidden and archived channels are returned. 
filteredQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        // Only archived group channels are returned.
    }
});

Filter channels by user IDs

To filter channels by user IDs, use the userIdsExactFilter or userIdsIncludeFilter. Let's assume the ID of the current user is Harry and the user is a member of two group channels:

  • channelA consists of Harry, John, and Jay.
  • channelB consists of Harry, John, Jay, and Jin.

A userIdsExactFilter returns a list of the current user's group channels containing exactly the queried user IDs. In case you specify only one user ID in the filter, the filter returns a list of the current user's one (distinct) or more 1-on-1 group channels with the specified user.

Light Color Skin
Copy
GroupChannelListQuery filteredQuery = GroupChannel.createMyGroupChannelListQuery();
List<String> userIds = new ArrayList<>();
userIds.add("John");
userIds.add("Jay");

filteredQuery.setUserIdsExactFilter(userIds);
filteredQuery.next(
    ...
    // Only 'channelA' is returned.
)

A userIdsIncludeFilter returns a list of the current user's group channels including the queried user IDs partially and exactly. Two different results can be returned according to the value of the queryType parameter.

Light Color Skin
Copy
GroupChannelListQuery filteredQuery = GroupChannel.createMyGroupChannelListQuery();
List<String> userIds = new ArrayList<>();
userIds.add("John");
userIds.add("Jay");
userIds.add("Jin");

filteredQuery.setUserIdsIncludeFilter(userIds, GroupChannelListQuery.QueryType.AND);
filteredQuery.next(
    ...
    // Only 'channelB' that include the ids {"John", "Jay", "Jin"} as a subset is returned.
)

filteredQuery.setUserIdsIncludeFilter(userIds, GroupChannelListQuery.QueryType.OR);
filteredQuery.next(
    ...
    // 'channelA' and 'channelB' that include {"John"}, plus 'channelA' and 'channelB' that include {"Jay"}, plus 'channelB' that include {"Jin"}.
    // Actually 'channelA' and 'channelB' are returned.
)

Send a message

Upon joining a group channel, a user can send messages of the following types:

  • UserMessage: a text message sent by a user.
  • FileMessage: a binary file message sent by a user.

You can additionally specify a CUSTOM_TYPE to further subclassify a message. When you send a text message, you can additionally attach arbitrary strings via a data field. You can utilize this field to send structured data such as font size, font type, or a custom JSON object.

Delivery failures due to the network issues return an exception. By overriding the onSent() callback in the context of sendUserMessage(), you can display messages that are successfully sent to a channel.

Light Color Skin
Copy
List<String> userIDsToMention = new ArrayList<>();
userIDsToMention.add("Jeff");
userIDsToMention.add("Julia");

List<String> metaArrayKeys = new ArrayList<>();
metaArrayKeys.add("linkTo");
metaArrayKeys.add("itemType");

List<String> translationTargetLanguages = new ArrayList<>();
translationTargetLanguages.add("fr");       // French
translationTargetLanguages.add("de");       // German

UserMessageParams params = new UserMessageParams()
        .setMessage(TEXT_MESSAGE)
        .setCustomType(CUSTOM_TYPE)
        .setData(DATA)
        .setMentionType(MentionType.USERS)      // Either USERS or CHANNEL
        .setMentionedUserIds(userIDsToMention)      // Or .setMentionedUsers(LIST_OF_USERS_TO_MENTION)
        .setMetaArrayKeys(metaArrayKeys)
        .setTranslationTargetLanguages(translationTargetLanguages)
        .setPushNotificationDeliveryOption(PushNotificationDeliveryOption.DEFAULT); // Either DEFAULT or SUPPRESS

groupChannel.sendUserMessage(params, new BaseChannel.SendUserMessageHandler() {
    @Override
    public void onSent(UserMessage userMessage, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

A user can also send any binary file through the SDK. The two ways to send a binary file are provided: by sending the file itself, or by sending a URL.

Sending a raw file indicates that you upload it to SendBird server and it can be downloaded from the server when needed in client apps. As another option, you can choose to send a file hosted on your server by passing a URL that represents the location of the file as a parameter. In this case, your file isn't hosted on SendBird server, and can be downloaded only from your own server instead.

Note: If you upload a file directly, a size limit is imposed per file depending on your plan. You can see your limit in the dashboard and adjust the limit via our sales team. No file size limit is imposed if you send a file message with its URL since the file isn't uploaded to SendBird server.

Light Color Skin
Copy
// Sending a file message with a raw file
List<FileMessage.ThumbnailSize> thumbnailSizes = new ArrayList<>(); // Allowed number of thumbnail images: 3
thumbnailSizes.add(new ThumbnailSize(100,100));
thumbnailSizes.add(new ThumbnailSize(200,200));

List<String> userIDsToMention = new ArrayList<>();
userIDsToMention.add("Jeff");
userIDsToMention.add("Julia");

List<String> metaArrayKeys = new ArrayList<>();
metaArrayKeys.add("linkTo");
metaArrayKeys.add("itemType");

List<String> translationTargetLanguages = new ArrayList<>();
translationTargetLanguages.add("fr");           // French
translationTargetLanguages.add("de");           // German

FileMessageParams params = new FileMessageParams()
        .setFile(FILE)              // Or .setFileURL(FILE_URL). You can also send a file message with a file URL.
        .setFileName(FILE_NAME)
        .setFileSize(FILE_SIZE)
        .setMimeType(MIME_TYPE)
        .setThumbnailSizes(thumbnailSizes)
        .setCustomType(CUSTOM_TYPE)
        .setData(DATA)
        .setMentionedType(MentionType.USERS)        // Either USERS or CHANNEL
        .setMentionedUserIds(userIDsToMention)      // Or .setMentionedUsers(LIST_OF_USERS_TO_MENTION)
        .setMetaArrayKeys(metaArrayKeys)
        .setTranslationTargetLanguages(translationTargetLanguages)
        .setPushNotificationDeliveryOption(PushNotificationDeliveryOption.DEFAULT); // Either DEFAULT or SUPPRESS

groupChannel.sendFileMessage(params, new BaseChannel.SendFileMessageHandler() {
    @Override
    public void onSent(FileMessage fileMessage, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Note: To send metadata along with a file, you can populate the DATA field.


Receive messages through a channel event handler

Messages sent from other members can be received through the onMessageReceived() method of a channel event handler. A BaseMessage object for each received message is one of the following three message types.

  • UserMessage: a text message sent by a user.
  • FileMessage: a binary file message sent by a user.
  • AdminMessage: a text message sent by an admin through the Platform API.

UNIQUE_HANDLER_ID is a unique identifier to register multiple concurrent handlers.

Light Color Skin
Copy
SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    @Override
    public void onMessageReceived(BaseChannel channel, BaseMessage message) {
        // TODO: Implement what is needed with the contents of the response in the 'message' parameter.
        if (message instanceof UserMessage) {
            // ...
        } else if (message instanceof FileMessage) {
            // ...
        } else if (message instanceof AdminMessage) {
            // ...
        }
    }
});

If the UI isn't valid anymore, remove the channel event handler.

Light Color Skin
Copy
SendBird.removeChannelHandler(UNIQUE_HANDLER_ID);

Mention other members in a message

When a member wants to call the attention of other members of a group channel, they can mention those members in a message. To do so, you should:

  1. Specify a list of the user IDs to mention.
  2. Add the list to either UserMessageParams or FileMessageParams which may contain options for further action.
  3. Pass the params to either sendUserMessage() or sendFileMessage().
  4. Then only up to 10 members mentioned in the message will be notified.
Light Color Skin
Copy
List<String> userIDsToMention = new ArrayList<>();
userIDsToMention.add("Harry");
userIDsToMention.add("Jay");
userIDsToMention.add("Jin");

UserMessageParams params = new UserMessageParams(MESSAGE)
    .setMentionedUserIds(userIDsToMention);

groupChannel.sendUserMessage(params, new BaseChannel.SendUserMessageHandler() {
    @Override
    public void onSent(UserMessage userMessage, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Load previous messages

Using the PreviousMessageListQuery's load() method which returns a list of BaseMessage objects, you can retrieve a set number of previous messages in a group channel. With a returned list, you can display the past messages in your UI once they have loaded.

Note: You can decide whether a user can see the messages sent prior to the user joining a group channel. In your dashboard, go to the Settings > Application > Messages tab, there is the Chat history option. If turned on, new users are allowed to view a message history in joined group channels. If turned off, new users aren't allowed to see the messages prior to joining a group channel.

Light Color Skin
Copy
// There should only be one single instance per channel view.
PreviousMessageListQuery prevMessageListQuery = groupChannel.createPreviousMessageListQuery();

...

// Retrieving previous messages.
prevMessageListQuery.load(LIMIT, REVERSE, new PreviousMessageListQuery.MessageListQueryResult() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});
ParameterTypeDescription

LIMIT

int

Specifies the number of results to return per call. Acceptable values are 1 to 100, inclusive. The recommended value for this parameter is 30.

REVERSE

boolean

Determines whether to sort the retrieved messages in the reversed order. If true, returns a list of messages which the latest comes at first and the earlist at last. the results are sorted in the reversed order. If false, returns a list of messages which the earlist comes at first and the latest at last.

A LIMIT parameter indicates how many messages should be included in a returned list. A PreviousMessageListQuery instance itself does pagination of a result set based on the value of the LIMIT parameter, and internally manages a token to retrieve the next page in the result set.

Each time the load() method is called, the instance retrieves a set number of messages in the next page and updates the value of the token to complete the current call and prepare a next call.

If you create a new PreviousMessageListQuery instance and call the load() method, a set number of the most recent messages are retrieved because its token has nothing to do with the previously created instance. So we recommend that you create a single query instance and store it as a member variable for traversing through the entire message history.

Note: Before invoking the load() method again, you must receive your onResult() callback first.


Load messages by timestamp or message ID

You can retrieve a set number of messages sent previously before a specific timestamp in a group channel, using the getPreviousMessagesByTimestamp() method.

Light Color Skin
Copy
groupChannel.getPreviousMessagesByTimestamp(TIMESTAMP, IS_INCLUSIVE, PREV_RESULT_SIZE, REVERSE, MESSAGE_TYPE, CUSTOM_TYPE, new BaseChannel.GetMessagesHandler() { 
    @Override
    public void onResult(List<BaseMessage> list, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }

        // A list of messages sent before the specified timestamp is successfully retrieved.
    }
});
ParameterTypeDescription

TIMESTAMP

long

Specifies the timestamp to be the reference point of a retrieval, in Unix milliseconds.

IS_INCLUSIVE

boolean

Determines whether to include the messages sent exactly on the TIMESTAMP.

PREV_RESULT_SIZE

int

Specifies the number of messages to retrieve. Note that the actual number of results may be larger than the set value when there are multiple messages with the same timestamp as the earliest message.

REVERSE

boolean

Determines whether to sort the retrieved messages in the reversed order.

MESSAGE_TYPE

enum

Specifies the message type to filter the messages with the corresponding type. Acceptable values are MessageTypeFilter.ALL, MessageTypeFilter.USER, MessageTypeFilter.FILE, and MessageTypeFilter.ADMIN.

CUSTOM_TYPE

string

Specifies the custom message type to filter the messages with the corresponding custom type.

Note: To retrieve messages sent after a specified timestamp, use the getNextMessagesByTimestamp() in a similar fashion. Using the getPreviousAndNextMessagesByTimestamp(), you can retrieve previous and next messages on both sides of a specific timestamp.

You can also retrieve a set number of messages sent previously before a specific message ID in a group channel, using the getPreviousMessagesById() method.

Light Color Skin
Copy
groupChannel.getPreviousMessagesById(MESSAGE_ID, IS_INCLUSIVE, PREV_RESULT_SIZE, REVERSE, MESSAGE_TYPE, CUSTOM_TYPE, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> list, SendBirdException e) {
        if (e != null) {        // Error.
            return;
        }

        // A list of messages, the IDs of which are ahead of the specified message ID, is successfully retrieved.
    }
});
ParameterTypeDescription

MESSAGE_ID

long

Specifies the unique ID of the message to be the reference point of a retrieval.

IS_INCLUSIVE

boolean

Determines whether to include the messages sent exactly on the TIMESTAMP.

PREV_RESULT_SIZE

int

Specifies the number of messages to retrieve. Note that the actual number of results may be larger than the set value when there are multiple messages with the same timestamp as the earliest message.

REVERSE

boolean

Determines whether to sort the retrieved messages in the reversed order.

MESSAGE_TYPE

enum

Specifies the message filtering option for the BaseChannel.MessageTypeFilter. Acceptable values are MessageTypeFilter.ALL, MessageTypeFilter.USER, MessageTypeFilter.FILE, and MessageTypeFilter.ADMIN.

CUSTOM_TYPE

string

Specifies the custom message type to filter the messages with the corresponding custom type.

Note: To retrieve messages sent after a specific message ID, use the getNextMessagesById() in a similar fashion. Using the getPreviousAndNextMessagesById() method, you can also retrieve previous and next messages on both sides of a specific message ID.


Update a message

A user can update any of their own text and file messages sent. An error is returned if a user attempts to update another user's messages. In addition, channel operators can update any messages sent in a channel.

Light Color Skin
Copy
// For a text message
UserMessageParams params = new UserMessageParams()
        .setMessage(NEW_TEXT_MESSAGE)
        .setCustomType(NEW_CUSTOM_TYPE)
        .setData(NEW_DATA);

// The MESSAGE_ID below indicates the unique message ID of a UserMessage object to update.
groupChannel.updateUserMessage(MESSAGE_ID, params, new BaseChannel.UpdateUserMessageHandler() {
    @Override
    public void onUpdated(UserMessage userMessage, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

...

// For a file message
FileMessageParams params = new FileMessageParams()
        .setFileURL(NEW_FIEL_URL)       // The file in a message can't be updated.
        .setFileName(NEW_FILE_NAME)
        .setFileSize(NEW_FILE_SIZE)
        .setData(NEW_DATA);

// The MESSAGE_ID below indicates the unique message ID of a FileMessage object to update.
groupChannel.updateFileMessage(MESSAGE_ID, params, new BaseChannel.UpdateFileMessageHandler() {
    @Override
    public void onUpdated(FileMessage fileMessage, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

The onMessageUpdated() method of a channel event handler will receive a callback from the server when a message is updated, and all members of the channel will be notified, including who has updated their own message.

Light Color Skin
Copy
SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    ...
    
    @Override
    public void onMessageUpdated(BaseChannel channel, long messageId) {
    
    }
    ...

});

Delete a message

A user can delete their own messages. An error is returned if a user attempts to delete messages sent by others. Also operators of a channel can delete any messages in a channel.

Light Color Skin
Copy
// The BASE_MESSAGE below indicates a BaseMessage object to delete. 
groupChannel.deleteMessage(BASE_MESSAGE, new BaseChannel.DeleteMessageHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

The onMessageDeleted() method of a channel event handler will receive a callback from the server when a message is deleted, and the result also notified to all other members in the channel, including who has just deleted their own message.

Light Color Skin
Copy
SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    ...

    @Override
    public void onMessageDeleted(BaseChannel channel, long messageId) {
    
    }
    ...

});

Clear the chat history

By using the resetMyHistory() method, you can help the current user clear the chat history in a group channel and start a fresh conversation with other members in the same channel. As the method's name implies, the chat history will be cleared only from the channel view of the current user, and will no longer be shown in that view. But the messages are not deleted from the database of the SendBird system, and other members can still see all the messages in their channel views.

This method simply clears the messages for the user by updating the lastMessage and readReceipt properties of a group channel object in addition to other internally managed data such as the number of the user’s unread message.

Note: This ability is effective only when the Chat history option is turned on in your dashboard under Settings > Application > Messages.

Light Color Skin
Copy
groupChannel.resetMyHistory(new GroupChannel.GroupChannelResetMyHistoryHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    //Error.
            return;
        }
    }
});

When a user is online, all data associated with the group channels they are a member of are automatically updated. However, when a user is disconnected from SendBird and reconnects later, you should call the refresh() method to update the user's group channels with the latest information.

Light Color Skin
Copy
groupChannel.refresh(new GroupChannel.GroupChannelRefreshHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    //Error.
            return;
        }
    }
});

Note: If you want to make your users see the channels updated to the most recent when their client apps are in the foreground, we recommend you call the refresh() within the onReconnectSucceeded() method which receives a callback from SendBird server when successfully reconnected.


Retrieve a list of all members

You can retrieve a list of all members in a group channel using the getMembers() method.

Light Color Skin
Copy
List<Member> members = groupChannel.getMembers();

Members of a group channel are automatically updated when a user is online. But when a user is disconnected from SendBird server and then reconnected, you should call the refresh() method to update the user's group channels with the latest information. See the Refresh all data related to a group channel section for the sample code.


Retrieve the online status of members

To stay updated on each member's connection status in a group channel, call the refresh() method before calling the getMembers() method to retrieve the members of the channel.

By calling the user.getConnectionStatus() method at each user object in a list which the getMembers() returns, you can retrieve the user's current connection status. The getConnectionStatus() returns one of the following two values:

  • User.ConnectionStatus.OFFLINE: the user is not connected to SendBird server.
  • User.ConnectionStatus.ONLINE: the user is connected to SendBird server.

Note: If your client app needs to keep track of the connection status of users in real time, we recommend that you call periodically the next() method of an ApplicationUserListQuery instance with its userIdsFilter filter specifed, perhaps in intervals of one minute or more.


Retrieve a list of banned or muted users

You can create a query to get a list of banned or muted users in a group channel. This query is only available for users who are registered as operators of a group channel.

Light Color Skin
Copy
// Retrieving banned users
BannedUserListQuery bannedUserListQuery = groupChannel.createBannedUserListQuery();
bannedUserListQuery.next(new UserListQuery.UserListQueryResultHandler() {
    @Override
    public void onResult(List<User> list, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

// Retrieving muted users
GroupChannelMemberListQuery memberListQuery = groupChannel.createMemberListQuery();
memberListQuery.setMutedMemberListFilteer(GroupChannelMemberListQuery.MutedMemberFilter.MUTED);
memberListQuery.next(new GroupChannelMemberListQuery.GroupChannelMemberListQueryResultHandler() {
    @Override
    public void onResult(List<Member> list, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

Ban and unban a user

Operators of a group channel can remove any users that behave inappropriately in the channel by using our Ban feature. Banned users are immediately expelled from a channel and allowed to join the channel again after the time period set by the operators. The operators can ban and unban users from group channels using the following code.

Light Color Skin
Copy
GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GroupChannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }

        // Banning and unbanning a user 
        if (groupChannel.getMyRole() == Member.Role.OPERATOR) {
            groupChannel.banUser(USER, DESCRIPTION, SECONDS, new GroupChannel.GroupChannelBanHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {    // Error.
                        return;
                    }

                    // TODO: Custom implementation for what should be done after banning.
                }
            });

            groupChannel.unbanUser(USER, new GroupChannel.GroupChannelUnbanHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {    // Error.
                        return;
                    }

                    // TODO: Custom implementation for what should be done after unbanning.
                }
            });
        }
    }
});

Note: You can also use banUserWithUserId() and unbanUserWithUserID() methods, instead of banUser() and unbanUser() methods, as they have the same abilities.


Mute and unmute a user

Operators of a group channel can prohibit the selected users from sending messages using our Mute feature. Muted users remain in the channel and are allowed to view the messages, but can't send any messages until the operators unmute them. The operators can mute and unmute users in group channels using the following code:

Light Color Skin
Copy
GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GrouphannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }

        // Muting and unmuting a user 
        if (groupChannel.getMyRole() == Member.Role.OPERATOR) {
            groupChannel.muteUser(USER, new groupChannel.GroupChannelMuteHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {    // Error.
                        return;
                    }
                    
                    // TODO: Custom implementation for what should be done after muting.
                }
            });

            groupChannel.unmuteUser(USER, new GroupChannel.GroupChannelUnmuteHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {    // Error.
                        return;
                    }
                    
                    // TODO: Custom implementation for what should be done after unmuting.
                }
            });
        }
    }
});

Note: You can also use muteUserWithUserId() and unmuteUserWithUserID() methods, instead of muteUser() and unmuteUser() methods, as they have the same abilities.


Report a message, a user, or a channel

In a group channel, a user can report suspicious or harrassing messages as well as the other users who use abusive language. The user can also report channels if there are any inappropriate content or activity within the channel. Based on this feature and our report API, you can build your own in-app system for managing objectionable content and subject.

Light Color Skin
Copy
// Reporting a message
groupChannel.reportMessage(MESSAGE_TO_REPORT, REPORT_CATEGORY, DESCRIPTION, new BaseChannel.ReportMessageHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

// Reporting a user
groupChannel.reportUser(OFFENDING_USER, REPORT_CATEGORY, DESCRIPTION, new BaseChannel.ReportUserHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});

// Reporting a channel
groupChannel.report(REPORT_CATEGORY, DESCRIPTION, new BaseChannel.ReportHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {    // Error.
            return;
        }
    }
});
ParameterTypeDescription

MESSAGE_TO_REPORT

object

Specifies the message to report for its suspicious, harassing, or inappropriate content.

OFFENDING_USER

object

Specifies the user who uses offensive or abusive language such as sending explicit messages or inappropriate comments.

REPORT_CATEGORY

enum

Specifies a report category which indicates the reason for reporting. Acceptable values are limited to ReportCategory.SUSPICIOUS, ReportCategory.HARASSING, ReportCategory.INAPPROPRIATE, and ReportCategory.SPAM.

DESCRIPTION

string

Specifies additional information to include in the report.