Chat SDKs Android v3
Chat SDKs Android
Chat SDKs
Android
Version 3
Sendbird Chat SDK v3 for Android is no longer supported as a new version is released. Check out our latest Chat SDK v4

Group channel

Copy link

A group channel is a chat that allows close interactions among a 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.

Note: To learn about differences between open channels and group channels, see Channel types.


Choose a type of a channel

Copy link

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

Private vs. Public

Copy link

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

A private channel can be used for 1-on-1 conversations, such as clinical consultations and Instagram-style Direct Messages, while a public channel for 1-to-N conversations, such as small group discussions among students.

1-to-1 vs. 1-to-N

Copy link

The distinct property determines whether to resume an old channel or to create a new one when someone attempts to open a channel with the same members. For a 1-to-1 chat, it is highly recommended that you turn on the distinct property to continuously use the existing channel.

Let's say there is a distinct group channel with user A, B, and C. If you attempt to create a new channel with the same members, the existing channel will be used. This is similar to Twitter-style 1-to-1 direct messaging. If the distinct property of the channel is set to false, a new channel will be created.

Note: The default value of this property is false. When a new member is invited or an existing member leaves the channel, then the distinct property of the channel is automatically turned off as well.

Supergroup vs. Group

Copy link

For occasions that demand engagement among a high volume of members, you can create a Supergroup channel, an expanded version of a group channel. It can be used for midsize conferences or large group discussion, such as company-wide stand-ups.

When the super property is set to true, a Supergroup channel will be created and up to tens of thousands of members can gather in the channel. The maximum number of members for a Supergroup channel can be adjusted depending on your Chat subscription plan.

Note: When super is set to true, distinct can't be supported.

Ephemeral vs. Persistent

Copy link

Messages sent in an ephemeral group channel are not saved in Sendbird's database. As such, old messages that are pushed out of a user's chat view due to new messages can't be retrieved. On the other hand, messages sent in a persistent group channel are stored permanently in the database by default.


Create a channel

Copy link

A user can create a group channel from inviting other users anytime in their client app. At the implementation level, you just need to write your code which passes the IDs of users to invite as an argument to a parameter in 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.

However, if you plan to create a Supergroup channel, the distinct property should be set to false.

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.

GroupChannel.createChannelWithUserIds(USER_IDS, IS_DISTINCT, new GroupChannel.GroupChannelCreateHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A group channel of the specified users is successfully created.
        // Through the "groupChannel" parameter of the onResult() callback method,
        // you can get the group channel's data from the result object that Sendbird server has passed to the callback method.
        String channelUrl = groupChannel.getUrl();
        ...
    }
});

When creating a channel, you can also append additional information like cover image and description by passing several arguments to the corresponding parameters.

GroupChannel.createChannel(USERS, IS_DISTINCT, NAME, COVER_IMAGE_OR_URL, DATA, CUSTOM_TYPE, new GroupChannel.GroupChannelCreateHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A group channel with additional information is successfully created.
        String channelUrl = groupChannel.getUrl();
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

USERS

list

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

IS_DISTINCT

boolean

Determines whether to reuse an existing channel or create a new channel. If set to true, returns a channel with the same users in the USERS or creates a new channel if no match is found.

* You can also use this property in conjunction with CUSTOM_TYPE and USER_IDS to create distinct channels for a specified channel custom type and a set of specified users. In order to enable the functionality, contact support on the Sendbird Dashboard.

IS_SUPER

boolean

Determines whether a new channel will be a Supergroup channel or a group channel. If set to true, the new channel can accommodate more than 2,000 members. When this argument is true, IS_DISTINCT is not supported and should be set to false.

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 channel information such as a long description of the channel or JSON formatted string.

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 method 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 Chat 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.

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)
        .setSuper(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) {
            // Handle error.
        }

        // A group channel with detailed configuration is successfully created.
        // By using groupChannel.getUrl(), groupChannel.getMembers(), groupChannel.getData(), groupChannel.getCustomType(), and so on,
        // you can access the result object from Sendbird server to check your GroupChannelParams configuration.
        String channelUrl = groupChannel.getUrl();
        ...
    }
});

Note: By default, the Allow creating group channels option is turned on which means that group channels can be created by any user with Sendbird Chat SDK. This may grant access to unwanted data or operations, leading to potential security concerns. To manage your access control settings, you can turn on or off each option in Settings > Application > Security > Access control list on Sendbird Dashboard.


Invite users as members

Copy link

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 > Chat > Channels > Group channels, 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.

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) {
            // Handle error.
        }

        ...
    }
});

Accept or decline an invitation from another user

Copy link

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. Otherwise, the invitation will be canceled if a user declines it. Since a user is allowed to join up to 2,000 group channels, the invitation to a user who already belongs to a maximum number of group channels will be canceled automatically.

// Accepting an invitation
groupChannel.acceptInvitation(new GroupChannel.GroupChannelAcceptInvitationHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

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

        ...
    }
});

By implementing the onUserReceivedInvitation() and onUserDeclinedInvitation() 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 option 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.

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) {
            // Handle error.
        }

        ...
    }
});

Join a channel as a member

Copy link

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. Since a user is allowed to join up to 2,000 group channels, a user who already belongs to a maximum number of group channels can't join a new channel.

if (groupChannel.isPublic()) {
    groupChannel.join(new GroupChannel.GroupChannelJoinHandler() {
        @Override
        public void onResult(SendBirdException e) {
            if (e != null) {
                // Handle error.
            }

            ...
        }
    });
}

Leave a channel

Copy link

A user can leave group channels as shown below. After leaving, the user can't receive messages from the channel, and this method can't be called for deactivated users.

groupChannel.leave(new GroupChannel.GroupChannelLeaveHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

Freeze and unfreeze a channel

Copy link

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 with each other but the operators can send a message to the channel.

// Freezing a channel
groupChannel.freeze(new GroupChannel.GroupChannelFreezeHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The channel successfully gets frozen.
        // You could display a message telling that chatting in the channel is unavailable, or do something in response to a successful operation.
        ...
    }
});

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

        // The channel successfully gets unfrozen.
        // You could display a message telling that chatting in the channel is available again, or do something in response to a successful operation.
        ...
    }
});

Delete a channel

Copy link

Only the operators of a group channel can delete the channel. Otherwise, an error is returned through the GroupChannelDeleteHandler.

Note: The following code works properly in the operators' client apps only.

groupChannel.delete(new GroupChannel.GroupChannelDeleteHandler() {
    @Override
    public void onResult(final SendBirdException e) {
        if (e != null) {
            // Handle error.
            return;
        }
        // The channel is successfully deleted.
    }
});

Retrieve a list of channels

Copy link

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

Note: Using the setIncludeEmpty() method of a GroupChannelListQuery instance, you can determine whether to include empty channels in the result. Empty channels are group channels that have been created but do not contain any messages, and are not included by default. However, if you turn off the Chat history option in your dashboard, you may retrieve empty channels in the result.

GroupChannelListQuery listQuery = GroupChannel.createMyGroupChannelListQuery();
listQuery.setIncludeEmpty(true);
listQuery.setMemberStateFilter(GroupChannelListQuery.MemberStateFilter.JOINED);
listQuery.setOrder(GroupChannelListQuery.Order.LATEST_LAST_MESSAGE);    // CHRONOLOGICAL, LATEST_LAST_MESSAGE, CHANNEL_NAME_ALPHABETICAL, and METADATA_VALUE_ALPHABETICAL
listQuery.setLimit(15);

listQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of matching group channels is successfully retrieved.
        // Through the "list" parameter of the onResult() callback method,
        // you can access the data of each group channel from the result list that Sendbird server has passed to the callback method.
        List<GroupChannel> channels = list;
        ...
    }
});

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

Note: Using the setIncludeEmpty() method of a PublicGroupChannelListQuery instance, you can determine whether to include empty channels in the result. Empty channels are group channels that have been created but do not contain any messages, and are not included by default. However, if you turn off the Chat history option in your dashboard, you may retrieve empty channels in the result.

PublicGroupChannelListQuery listQuery = GroupChannel.createPublicGroupChannelListQuery();
listQuery.setIncludeEmpty(true);
listQuery.setMembershipFilter(PublicGroupChannelListQuery.MembershipFilter.JOINED);
listQuery.setOrder(PublicGroupChannelListQuery.Order.CHANNEL_NAME_ALPHABETICAL);    // CHRONOLOGICAL, CHANNEL_NAME_ALPHABETICAL, and METADATA_VALUE_ALPHABETICAL
listQuery.setLimit(15);

listQuery.next(new PublicGroupChannelListQuery.PublicGroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of public group channels matching search criteria is successfully retrieved.
        // Through the "list" parameter of the onResult() callback method,
        // you can access the data of each group channel from the result list that Sendbird server has passed to the callback method.
        List<GroupChannel> channels = list;
        ...
    }
});

Note: Refer to this section in the Advanced page for information on how to search for specific group channels with keywords and filters.


Retrieve a channel by URL

Copy link

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

GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GroupChannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // Through the "groupChannel" parameter of the onResult() callback method,
        // the group channel object identified with the CHANNEL_URL is returned by Sendbird server,
        // and you can get the group channel's data from the result object.
        String channelName = groupChannel.getName();
        ...
    }
});

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

Copy link

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

// Hiding (archiving) a group channel.
groupChannel.hide(IS_HIDE_PREVIOUS_MESSAGES, IS_ALLOW_AUTO_UNHIDE, new GroupChannel.GroupChannelHideHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The channel successfully gets hidden from the list.
        // The current user's channel view should be refreshed to reflect the change.
        ...
    }
});

// Unhiding a group channel.
groupChannel.unhide(new GroupChannel.GroupChannelUnhideHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The channel successfully gets unhidden from the list.
        // The current user's channel view should be refreshed to reflect the change.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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.

if (groupChannel.getHiddenState() == GroupChannel.HiddenState.UNHIDDEN) {
    // Display the channel in the list.
} else if (groupChannel.getHiddenState() == GroupChannel.HiddenState.HIDDEN_ALLOW_AUTO_UNHIDE) {
    // Hide the channel from the list, and get it appeared back on condition.
} else if (groupChannel.getHiddenState() == GroupChannel.HiddenState.HIDDEN_PREVENT_AUTO_UNHIDE) {
    // Archive the channel, and get it appeared back in the list only when the unhide() is called.
}

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

GroupChannelListQuery listQuery = GroupChannel.createMyGroupChannelListQuery();
listQuery.setIncludeEmpty(true);
// The filter options are UNHIDDEN, HIDDEN, HIDDEN_ALLOW_AUTO_UNHIDE, HIDDEN_PREVENT_AUTO_UNHIDE, and ALL.
// If set to HIDDEN, hidden and archived channels are returned.
listQuery.setHiddenChannelFilter(GroupChannelListQuery.HiddenChannelFilter.HIDDEN_PREVENT_AUTO_UNHIDE);

listQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        // Only archived channels are returned in a result list through the "list" parameter of the onResult() callback method.
        ...
    }
});

Filter channels by user IDs

Copy link

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-to-1 group channels with the specified user.

GroupChannelListQuery listQuery = GroupChannel.createMyGroupChannelListQuery();
List<String> userIds = new ArrayList<>();
userIds.add("John");
userIds.add("Jay");

listQuery.setUserIdsExactFilter(userIds);

listQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        // Only channelA is returned in a result list through the "list" parameter of the onResult() callback method.
        ...
    }
});

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.

GroupChannelListQuery listQuery = GroupChannel.createMyGroupChannelListQuery();
List<String> userIds = new ArrayList<>();
userIds.add("John");
userIds.add("Jay");
userIds.add("Jin");

listQuery.setUserIdsIncludeFilter(userIds, GroupChannelListQuery.QueryType.AND);

listQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        // Only channelB including {'John', 'Jay', 'Jin'} as a subset is returned in a result list.
        ...
    }
});

listQuery.setUserIdsIncludeFilter(userIds, GroupChannelListQuery.QueryType.OR);
listQuery.next(new GroupChannelListQuery.GroupChannelListQueryResultHandler() {
    @Override
    public void onResult(List<GroupChannel> list, SendBirdException e) {
        // channelA and channelB including {'John'}, channelA and channelB including {'Jay'}, channelB that including {'Jin'}.
        // Actually, channelA and channelB are returned in a result list.
        ...
    }
});

Send a message

Copy link

In a group channel, users can send messages of the following types:

Message typeClassDescription

Text

UserMessage

A text message sent by a user

File

FileMessage

A binary file message sent by a user

In addition to these message types, you can further subclassify a message by specifying its custom type. This custom type takes on the form of a String and can be used to search or filter messages. It allows you to append information to your message and customize message categorization.

The following code shows several types of parameters that you can configure to customize text messages by using UserMessageParams. Under the UserMessageParams object, you can assign specific values to message, data and other properties. By assigning arbitrary string to the data property, you can set custom font size, font type or JSON object. To send your messages, you need to pass the UserMessageParams object as an argument to the parameter in the sendUserMessage() method.

Through the onSent() callback method of the sendUserMessage() method, Sendbird server always notifies whether your message has been successfully sent to the channel. When there is a delivery failure due to network issues, an exception is returned through the callback method.

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

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)
        .setMetaArrays(Arrays.asList(new MessageMetaArray("itemType", Arrays.asList("tablet")), new MessageMetaArray("quality", Arrays.asList("best", "good")))
        .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) {
            // Handle error.
        }

        // A text message with detailed configuration is successfully sent to the channel.
        // By using userMessage.getMessageId(), userMessage.getMessage(), userMessage.getCustomType(), and so on,
        // you can access the result object from Sendbird server to check your UserMessageParams configuration.
        // The current user can receive messages from other users through the onMessageReceived() method of an event handler.
        long messageId = userMessage.getMessageId();
        ...
    }
});

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

Sending a raw file means you're uploading it to Sendbird server where it can be downloaded in client apps. When you upload a file directly to the server, there is a size limit imposed on the file depending on your plan. You can see the limit in your dashboard and adjust it with our sales team.

The other option is to send a file hosted on your server. You can pass the file's URL, which represents its location, as an argument to a parameter. In this case, your file is not hosted on Sendbird server and it can only be downloaded from your own server. When you send a file message with a URL, there is no limit on the file size since it's not directly uploaded to Sendbird server.

Note: You can use sendFileMessages(), which is another method that allows you to send up to 20 file messages per one method call. Refer to our API Reference to learn more about it.

The following code shows several types of parameters that you can configure to customize file messages by using FileMessageParams. Under the FileMessageParams object, you can assign specific values to customType and other properties. To send your messages, you need to pass the FileMessageParams object as an argument to the parameter in the sendFileMessage() method.

Through the onSent() callback method of the sendFileMessage() method, Sendbird server always notifies whether your message has been successfully sent to the channel. When there is a delivery failure due to network issues, an exception is returned through the callback method.

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

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)
        .setMentionedType(MentionType.USERS)        // Either USERS or CHANNEL
        .setMentionedUserIds(userIDsToMention)      // Or .setMentionedUsers(LIST_OF_USERS_TO_MENTION)
        .setPushNotificationDeliveryOption(PushNotificationDeliveryOption.DEFAULT); // Either DEFAULT or SUPPRESS

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

        // A file message with detailed configuration is successfully sent to the channel.
        // By using fileMessage.getMessageId(), fileMessage.getFileName(), fileMessage.getCustomType(), and so on,
        // you can access the result object from Sendbird server to check your FileMessageParams configuration.
        // The current user can receive messages from other users through the onMessageReceived() method of an event handler.
        long messageId = fileMessage.getMessageId();
        ...
    }
});

Send a critical alert message to iOS devices

Copy link

A critical alert is a notification that can be sent to iOS devices even when mute or Do Not Disturb is turned on. Critical alert messages can be sent to iOS devices through the sendUserMessage() and sendFileMessage() methods. To do so, create an AppleCriticalAlertOptions instance and set it as an attribute of a UserMessageParams instance. Then pass the created UserMessageParams instance as an argument to a parameter in the sendUserMessage() or sendFileMessage() method.

Note: To learn more about how to set critical alerts, visit Apple critical alerts.

UserMessageFileMessage
// Send a critical alert user message.
final UserMessageParams userMessageParams = new UserMessageParams();
final AppleCriticalAlertOptions options = new AppleCriticalAlertOptions("name", 0.7); // Acceptable values for `volume` range from 0 to 1.0, inclusive.
userMessageParams.setAppleCriticalAlertOptions(options);

groupChannel.sendUserMessage(userMessageParams, new BaseChannel.SendUserMessageHandler() {
    @Override
    public void onSent(UserMessage message, SendBirdException e) {
        // Handle error.
    }
});

Receive messages through a channel event handler

Copy link

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.

Message typeClassDescription

Text

UserMessage

A text message sent by a user

File

FileMessage

A binary file message sent by a user

Admin

AdminMessage

A text message sent by an admin through the Chat API

UNIQUE_HANDLER_ID is a unique identifier to register multiple concurrent handlers.

SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    @Override
    public void onMessageReceived(BaseChannel channel, BaseMessage message) {
        // You can customize how to display the different types of messages with the result object 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.

SendBird.removeChannelHandler(UNIQUE_HANDLER_ID);

Reply to a message

Copy link

You can reply to a specific message in a channel through the sendUserMessage() or sendFileMessage() method. To do so, you should create a UserMessageParams or a FileMessageParams object and then specify the parentMessageId property of the object. Sending reply messages works the same way as sending regular messages to a channel except replies have an additional parentMessageId property.

Reply with a text message

Copy link

When replying to a message through the sendUserMessage() method, specify and pass a UserMessageParams object as an argument to a parameter in the method.

// Create a `UserMessageParams` object.
UserMessageParams params = new UserMessageParams();
params.setParentMessageId(PARENT_MESSAGE_ID);
...

// Pass the params to the parameter of the `sendUserMessage()` method.
groupChannel.sendUserMessage(params, new BaseChannel.SendUserMessageHandler() {
    @Override
    public void onSent(UserMessage userMessage, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A reply to a specific message in the form of a text message is successfully sent.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

PARENT_MESSAGE_ID

long

Specifies the unique ID of a parent message. A parent message is a message that has a thread of replies. If the message sent through the sendUserMessage() method is a parent message, the value of this property is 0. If the message is a reply to a parent message, the value is the message ID of the parent message.

Reply with a file message

Copy link

When replying with a file message through the sendFileMessage() method, you should specify and pass a FileMessageParams object as an argument to a parameter in the method.

// Create a `FileMessageParams` object.
FileMessageParams params = new FileMessageParams();
params.setParentMessageId(PARENT_MESSAGE_ID);
...

// Pass the params to the parameter in the `sendFileMessage()` method.
groupChannel.sendFileMessage(params, new BaseChannel.SendFileMessageHandler() {
    @Override
    public void onSent(FileMessage userMessage, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A reply to a specific message in the form of a file message is successfully sent.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

PARENT_MESSAGE_ID

long

Specifies the unique ID of a parent message. A parent message is a message that has a thread of replies. If the message sent through the sendFileMessage() method is a parent message, the value of this property is 0. If the message is a reply to a parent message, the value is the message ID of the parent message.


Mention other members in a message

Copy link

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. Up to 10 members mentioned in the message will be notified.

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) {
            // Handle error.
        }

        ...
    }
});

React to a message

Copy link

Message reactions will help you build a more engaging chat experience that goes beyond text messages. They are a quick and easy way for users to respond to a message. Users can express their acknowledgement of or feelings about a message without written text by simply adding reactions. They can also view and delete their reactions to the message.

Note: Currently, message reactions are only available in group channels.

String emojiKey = "smile";

// The BASE_MESSAGE below indicates a BaseMessage object to add a reaction to.
groupChannel.addReaction(BASE_MESSAGE, emojiKey, new BaseChannel.ReactionHandler() {
    @Override
    public void onResult(ReactionEvent reactionEvent, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

// The BASE_MESSAGE below indicates a BaseMessage object to delete a reaction from.
groupChannel.deleteReaction(BASE_MESSAGE, emojiKey, new BaseChannel.ReactionHandler() {
    @Override
    public void onResult(ReactionEvent reactionEvent, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

// Note: To add or remove the emoji of which key matches 'smile' below the message on the current user's chat view,
// the applyReactionEvent() method should be called in the channel event handler's onReactionUpdated() method.

You can decide how to display reactions that were added to messages in the current user’s chat view.

Note: getPreviousMessagesByTimestamp(), getNextMessagesByTimestamp(), getPreviousAndNextMessagesByTimestamp() are deprecated. Accordingly, use the getMessagesByTimestamp() method instead.

MessageListParams params = new MessageListParams();
params.setInclusive(IS_INCLUSIVE);
params.setPreviousResultSize(PREVIOUS_RESULT_SIZE);
params.setNextResultSize(NEXT_RESULT_SIZE);
params.setReverse(REVERSE);
params.setIncludeReactions(INCLUDE_REACTIONS);
...

groupChannel.getMessagesByTimestamp(TIMESTAMP, params, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> list, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        for (BaseMessage message : list) {
            ...
            for (Reaction reaction : message.getReactions()) {
                List<String> userIds = reaction.getUserIds();

                // Check if this emoji has been used when the current user reacted to the message.
                if (userIds.contains(SendBird.getCurrentUser().getUserId())) {
                    String key = reaction.getKey();
                    long updatedAt = reaction.getUpdatedAt();

                    // Show the emoji however you want on the current user's chat view.
                }
            }
        }
    }
});

Note: Messages along with their reactions can also be retrieved by using the PreviousMessageListQuery's load() method. To learn more, refer to the Load previous messages section below.

If one of the channel members reacts to a message, the onReactionUpdated() method in the channel event handler will be invoked on all channel members’ devices including the one that made the reaction. The applyReactionEvent() method will reflect the reaction change to the message in real time.

SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    ...

    @Override
    public void onReactionUpdated(BaseChannel channel, ReactionEvent reactionEvent) {
        ...

        // If there is a message with the reactionEvent.getMessageId(),
        // you can apply the reaction change to the message by calling the applyReactionEvent() method.
        message.applyReactionEvent(reactionEvent);

        // Add or remove an emoji below the message on the current user's chat view.
    }

    ...
});

Load previous messages

Copy link

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 > Chat > Channels > Group channels, 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.

// There should only be one single instance per channel view.
PreviousMessageListQuery listQuery = groupChannel.createPreviousMessageListQuery();
listQuery.setIncludeMetaArray(true);    // Retrieve a list of messages along with their metaarrays.
listQuery.setIncludeReactions(true);    // Retrieve a list of messages along with their reactions.
...

// Retrieving previous messages.
listQuery.load(LIMIT, REVERSE, new PreviousMessageListQuery.MessageListQueryResult() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
                // Handle error.
        }

        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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 reverse order. If true, returns a list of messages which the latest comes at first and the earliest at last. the results are sorted in reverse order. If false, returns a list of messages which the earliest 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.

The following table shows all the supported filters for PreviousMessageListQuery to search for messages you want to retrieve. You can use any filters in a similar fashion with the sample code above.

List of filters

Copy link
NameFilters...

MessageTypeFilter

Messages with the specified message type. The setMessageTypeFilter() method can be used to enable this filter.

CustomTypeFilter

Messages with the specified custom type. The setCustomTypeFilter() method can be used to enable this filter.

SenderUserIdsFilter

Messages that are sent by the specified users. The setSenderIdsFilter() method can be used to enable this filter.


Load messages by timestamp or message ID

Copy link

Using the getMessagesByTimestamp() method, you can retrieve a set number of previous and next messages on both sides of a specific timestamp in a group channel.

The following code shows several types of parameters that you can configure to customize a message query by using MessageListParams. Under the MessageListParams object, you can assign values to previousResultSize, messageType, customType, and other properties. To retrieve messages in a channel, you need to pass the MessageListParams object as an argument to the parameter in the getMessagesByTimestamp() method.

MessageListParams params = new MessageListParams();
params.setInclusive(IS_INCLUSIVE);
params.setPreviousResultSize(PREVIOUS_RESULT_SIZE);
params.setNextResultSize(NEXT_RESULT_SIZE);
params.setReverse(REVERSE);
params.setMessageType(MESSAGE_TYPE);
params.setCustomType(CUSTOM_TYPE);
...

groupChannel.getMessagesByTimestamp(TIMESTAMP, params, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of previous and next messages on both sides of a specified timestamp is successfully retrieved.
        // Through the "messages" parameter of the onResult() callback method,
        // you can access and display the data of each message from the result list that Sendbird server has passed to the callback method.
        List<BaseMessage> messages = messages;
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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, which are sent previously before a specified timestamp. 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.

NEXT_RESULT_SIZE

int

Specifies the number of messages to retrieve, which are sent later after a specified timestamp. 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 latest message.

REVERSE

boolean

Determines whether to sort the retrieved messages in reverse 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.

You can also retrieve a set number of previous and next messages on both sides of a specific message ID in a group channel, using the getMessagesByMessageId() method and MessageListParams object.

MessageListParams params = new MessageListParams();
params.setInclusive(IS_INCLUSIVE);
params.setPreviousResultSize(PREVIOUS_RESULT_SIZE);
params.setNextResultSize(NEXT_RESULT_SIZE);
params.setReverse(REVERSE);
params.setMessageType(MESSAGE_TYPE);
params.setCustomType(CUSTOM_TYPE);
...

groupChannel.getMessagesByMessageId(MESSAGE_ID, params, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of previous and next messages on both sides of a specified message ID is successfully retrieved.
        // Through the "messages" parameter of the onResult() callback method,
        // you can access and display the data of each message from the result list that Sendbird server has passed to the callback method.
        List<BaseMessage> messages = messages;
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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 message identified with a specified message ID.

PREV_RESULT_SIZE

int

Specifies the number of messages to retrieve, which are sent previously before a specified message ID.

NEXT_RESULT_SIZE

int

Specifies the number of messages to retrieve, which are sent later after a specified timestamp.

REVERSE

boolean

Determines whether to sort the retrieved messages in reverse 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.


List messages along with their replies

Copy link

You can retrieve messages and their replies in a specific thread through one of the load(), getMessagesByTimestamp(), or getMessagesByMessageId() methods.

Load channel messages

Copy link

The load() method of a PreviousMessageListQuery instance returns a list of BaseMessage objects. By using this method, you can retrieve previous messages in a specific channel.

PreviousMessageListQuery listQuery = groupChannel.createPreviousMessageListQuery();
listQuery.setLimit(LIMIT);
listQuery.setReverse(REVERSE);
listQuery.setReplyTypeFilter(ReplyTypeFilter.ALL);
listQuery.setMessagePayloadFilter(
        new MessagePayloadFilter.Builder()
                .setIncludeParentMessageInfo(true)
                .setIncludeThreadInfo(true)
                .build()
);
...

// This retrieves previous messages in a channel.
listQuery.load(new PreviousMessageListQuery.MessageListQueryResult() {
    @Override
    public void onResult(List<BaseMessage> list, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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 reverse order. If false, the results are in ascending order.

INCLUDE_THREAD_INFO

boolean

Determines whether to include the information of the message thread in the results that contain parent messages.

REPLY_TYPE_FILTER

enum

Specifies the type of message to include in the results.
- NONE (default): All messages that are not replies. These message may or may not have replies in its thread.
- ALL: All messages including threaded and non-threaded parent messages as well as its replies.
- ONLY_REPLY_TO_CHANNEL: Messages that are not threaded. It only includes the parent messages and replies that were sent to the channel.

INCLUDE_PARENT_MESSAGE_INFO

boolean

Determines whether to include the information of the parent messages in the result. (Default: false)

INCLUDE_REPLIES

boolean

(Deprecated) Determines whether to include replies in the results.

INCLUDE_PARENT_MESSAGE_TEXT

boolean

(Deprecated) Determines whether to include the parent message text in the results when the retrieved messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.

Load messages by timestamp or message ID

Copy link

The getMessagesByTimestamp() and getMessagesByMessageId() methods of a BaseChannel instance returns a list of BaseMessage objects.

When using either of the methods above, you can also pass a MessageListParams object as an argument to the parameter in those methods.

MessageListParams params = new MessageListParams();
params.setPreviousResultSize(PREV_RESULT_SIZE);
params.setNextResultSize(NEXT_RESULT_SIZE);
params.setInclusive(INCLUSIVE);
params.setReverse(REVERSE);
params.setReplyTypeFilter(ReplyTypeFilter.ALL, ReplyTypeFilter.ONLY_REPLY_TO_CHANNEL, ReplyTypeFilter.NONE);
params.setMessagePayloadFilter();

List of arguments

Copy link
ArgumentTypeDescription

PREV_RESULT_SIZE

int

Specifies the number of messages to retrieve that were sent before the specified timestamp or message ID.

NEXT_RESULT_SIZE

int

Specifies the number of messages to retrieve that were sent after the specified timestamp or message ID.

INCLUSIVE

boolean

Determines whether to include the messages with the matching timestamp or message ID in the results.

REVERSE

boolean

Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

INCLUDE_THREAD_INFO

boolean

Determines whether to include the information of the message thread in the results that contain parent messages.

REPLY_TYPE_FILTER

enum

Specifies the type of message to include in the results.
- NONE (default): All messages that are not replies. These message may or may not have replies in its thread.
- ALL: All messages including threaded and non-threaded parent messages as well as its replies.
- ONLY_REPLY_TO_CHANNEL: Messages that are not threaded. It only includes the parent messages and replies that were sent to the channel.

INCLUDE_PARENT_MESSAGE_INFO

boolean

Determines whether to include the information of the parent messages in the result. (Default: false)

INCLUDE_REPLIES

boolean

(Deprecated) Determines whether to include replies in the results.

INCLUDE_PARENT_MESSAGE_TEXT

boolean

(Deprecated) Determines whether to include the parent message text in the results when the messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.

By timestamp

Copy link

The getMessagesByTimestamp() method retrieves a set number of previous and next messages on both sides of a specific timestamp in a channel.

groupChannel.getMessagesByTimestamp(TIMESTAMP, params, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of previous and next messages on both sides of a specified timestamp is successfully retrieved.
        // Through the "messages" parameter of the onResult() callback method,
        // you can access and display the data of each message from the result list that Sendbird server has passed to the callback method.
        List<BaseMessage> messages = messages;
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

TIMESTAMP

long

Specifies the timestamp to be the reference point for messages to retrieve, in Unix milliseconds format. Messages sent before or after the timestamp can be retrieved.

By message ID

Copy link

The getMessagesByMessageId() method retrieves a set number of previous and next messages on both sides of a specific message ID in a channel.

groupChannel.getMessagesByMessageId(MESSAGE_ID, params, new BaseChannel.GetMessagesHandler() {
    @Override
    public void onResult(List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of previous and next messages on both sides of a specified message ID is successfully retrieved.
        // Through the "messages" parameter of the onResult() callback method,
        // you can access and display the data of each message from the result list that Sendbird server has passed to the callback method.
        List<BaseMessage> messages = messages;
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

MESSAGE_ID

long

Specifies the message ID to be the reference point for messages to retrieve. Messages sent before or after the message with the matching message ID can be retrieved.


List replies of a parent message

Copy link

You can retrieve replies of a parent message if you can determine the parent message like the following. First, create a ThreadMessageListParams object and set properties related to the thread where the target replies belong to. Then pass the params into the getThreadedMessagesByTimestamp() method.

// Create a `ThreadMessageListParams` object.
ThreadMessageListParams params = new ThreadMessageListParams();
params.setPreviousResultSize(PREV_RESULT_SIZE);
params.setNextResultSize(NEXT_RESULT_SIZE);
params.setInclusive(INCLUSIVE);
params.setReverse(REVERSE);
params.setMessagePayloadFilter();
...

// Pass the params as an argument to the parameter in the `getThreadedMessagesByTimestamp()` method.
parentMessage.getThreadedMessagesByTimestamp(TIMESTAMP, params, new BaseMessage.GetThreadedMessagesHandler() {
    @Override
    public void onResult(BaseMessage parentMessage, List<BaseMessage> messages, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // A list of replies of the specified parent message timestamp is successfully retrieved.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

TIMESTAMP

long long

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

PREV_RESULT_SIZE

int

Specifies the number of messages to retrieve that were sent before the specified timestamp.

NEXT_RESULT_SIZE

int

Specifies the number of messages to retrieve that were sent after the specified timestamp.

INCLUSIVE

boolean

Determines whether to include the messages with the matching timestamp in the results.

REVERSE

boolean

Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

INCLUDE_PARENT_MESSAGE_INFO

boolean

Determines whether to include the information of the parent messages in the result. (Default: false)

INCLUDE_PARENT_MESSAGE_TEXT

boolean

(Deprecated) Determines whether to include the parent message text in the results when the messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.


Retrieve a message

Copy link

You can retrieve a specific message by creating and passing the MessageRetrievalParams object into the getMessage() method as a parameter.

// Create a `MessageRetrievalParams` object.
MessageRetrievalParams params = new MessageRetrievalParams(CHANNEL_URL, CHANNEL_TYPE, MESSAGE_ID);
...

// Pass the params as an argument to the parameter in the `getMessage()` method.
BaseMessage.getMessage(params, new BaseMessage.GetMessageHandler() {
    @Override
    public void onResult(BaseMessage message, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The specified message is successfully retrieved.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

CHANNEL_URL

String

Specifies the URL of the channel to retrieve the message.

CHANNEL_TYPE

BaseChannel.ChannelType

Specifies the type of the channel.

MESSAGE_ID

long

Specifies the unique ID of the message to retrieve.


Update a message

Copy link

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.

User messageFile 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) {
            // Handle error.
        }

        // The message is successfully updated.
        // Through the "userMessage" parameter of the onUpdated() callback method,
        // you could check if the update operation has been performed right.
        String text = userMessage.getMessage();
        ...
    }
});

If a message is updated, the onMessageUpdated() method in the channel event handler will be invoked on all channel members' devices except the one that updated the message.

SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    ...

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

    ...
});

Delete a message

Copy link

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.

// 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) {
            // Handle error.
        }

        // The message is successfully deleted from the channel.
        ...
    }
});

If a message is deleted, the onMessageDeleted() method in the channel event handler will be invoked on all channel members' devices including the one that deleted the message.

SendBird.addChannelHandler(UNIQUE_HANDLER_ID, new SendBird.ChannelHandler() {
    ...

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

    ...
});

Copy a message

Copy link

A user can copy and send their own message in the same channel or to another channel.

User messageFile message
groupChannel.copyUserMessage(TARGET_CHANNEL, MESSAGE_TO_COPY, new BaseChannel.CopyUserMessageHandler() {
    @Override
    public void onCopied(UserMessage userMessage, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The message is successfully copied to the target channel.
        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

TARGET_CHANNEL

object

Specifies a target channel to send a copied message to.

MESSAGE_TO_COPY

object

Specifies a message to copy.

HANDLER

interface

Specifies the handler interface which contains the onCopied() callback method to receive the response from Sendbird server for a message copy request.


Clear the chat history

Copy link

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.

groupChannel.resetMyHistory(new GroupChannel.GroupChannelResetMyHistoryHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

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 server and reconnects later, you should call the refresh() method to update the user's group channels with the latest information.

groupChannel.refresh(new GroupChannel.GroupChannelRefreshHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

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

Copy link

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

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

Copy link

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:

getConnectionStatus()

Copy link
ValueDescription

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 specified, perhaps in intervals of one minute or more.


Retrieve a list of members and operators in a specific order

Copy link

Using the next() method of a GroupChannelMemberListQuery instance, the members and operators of a group channel can be retrieved. For a specific order, set one of the options in the following table to the setOrder() method of GroupChannelMemberListQuery.

GroupChannelMemberListQuery.Order

Copy link
ValueDescription

MEMBER_NICKNAME_ALPHABETICAL

The members are arranged in an alphabetical order (Default).

OPERATOR_THEN_MEMBER_ALPHABETICAL

The operators are sequenced before the members, both in an alphabetical order.

final GroupChannelMemberListQuery listQuery = groupChannel.createMemberListQuery();
listQuery.setLimit(10);
listQuery.setOrder(GroupChannelMemberListQuery.Order.OPERATOR_THEN_MEMBER_ALPHABETICAL);

while (listQuery.hasNext()) {
    listQuery.next(new GroupChannelMemberListQueryResultHandler() {
        @Override
        public void onResult(List<Member> list, SendBirdException e) {
            if (e != null) {
                // Handle error.
            }

            // A list of matching members and operators is successfully retrieved.
            // Through the "list" parameter of the callback method,
            // you can access the data of each item from the result list that Sendbird server has passed to the callback method.
            List<member> members = list;
            ...
        }
    }
}

GroupChannelMemberListQuery.OperatorFilter

Copy link

For filtering, set one of the options in the following table to the GroupChannelMemberListQuery's setOperatorFilter() method.

ValueDescription

ALL

No filter is applied to the group channel list (Default).

OPERATOR

Only operators are retrieved for the list.

NONOPERATOR

Members, except for operators, are retrieved for the list.

final GroupChannelMemberListQuery listQuery = groupChannel.createMemberListQuery();
listQuery.setLimit(10);
listQuery.setOperatorFilter(GroupChannelMemberListQuery.OperatorFilter.OPERATOR);    // ALL, OPERATOR, and NONOPERATOR

while (listQuery.hasNext()) {
    listQuery.next(new GroupChannelMemberListQuery.GroupChannelMemberListQueryResultHandler() {
        @Override
        public void onResult(List<Member> list, SendBirdException e) {
            if (e != null) {
                // Handle error.
            }

            // A list of matching members and operators is successfully retrieved.
            // Through the "list" parameter of the callback method,
            // you can access the data of each item from the result list that Sendbird server has passed to the callback method.
            List<member> members = list;
            ...
        }
    }
}

Retrieve a list of operators

Copy link

You can get a list of operators who monitor and control the activities in a group channel by using the next() method of an OperatorListQuery instance which returns a list of User objects.

OperatorListQuery listQuery = groupChannel.createOperatorListQuery();
while (listQuery.hasNext()) {
    listQuery.next(new OperatorListQuery.OperatorListQueryResultHandler() {
        @Override
        public void onResult(List<User> list, SendBirdException e) {
            if (e != null) {
                // Handle error.
            }

            // A list of the operators of the channel is successfully retrieved.
            // Through the "list" parameter of the onResult() callback method,
            // you can access and display the data of each operator from the result list that Sendbird server has passed to the callback method.
            List<user> operators = list;
            ...
        }

        ...
    });
}

Register operators

Copy link

You can register members as operators of a group channel.

groupChannel.addOperators(USER_IDS, new AddOperatorsHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The participants are successfully registered as operators of the channel.
        ...
    }
});

Cancel the registration of operators

Copy link

You can cancel the registration of operators from a group channel but leave them as members.

groupChannel.removeOperators(USER_IDS, new RemoveOperatorsHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The cancel operation is succeeded,
        // and you could display some message to those who are not operators anymore.
        ...
    }
});

If you want to cancel the registration of all operators in a channel at once, use the following code.

groupChannel.removeAllOperators(new RemoveAllOperatorsHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        // The cancel operation is succeeded,
        // and you could display some message to those who are not operators anymore.
        ...
    }
});

Retrieve a list of banned or muted users

Copy link

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.

// Retrieving banned users.
BannedUserListQuery listQuery = groupChannel.createBannedUserListQuery();
listQuery.next(new UserListQuery.UserListQueryResultHandler() {
    @Override
    public void onResult(List<User> list, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

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

        ...
    }
});

Ban and unban a user

Copy link

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.

GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GroupChannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        if (groupChannel.getMyRole() == Member.Role.OPERATOR) {
            // Ban a user.
            groupChannel.banUser(USER, DESCRIPTION, SECONDS, new GroupChannel.GroupChannelBanHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {
                        // Handle error.
                    }

                    // The user is successfully banned from the channel.
                    // You could notify the user of being banned by displaying a prompt.
                    ...
                }
            });

            // Unban a user.
            groupChannel.unbanUser(USER, new GroupChannel.GroupChannelUnbanHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {
                        // Handle error.
                    }

                    // The user is successfully unbanned from the channel.
                    // You could notify the user of being unbanned by displaying a prompt.
                    ...
                }
            });
        }
    }
});

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


Mute and unmute a user

Copy link

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:

GroupChannel.getChannel(CHANNEL_URL, new GroupChannel.GroupChannelGetHandler() {
    @Override
    public void onResult(GroupChannel groupChannel, SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        if (groupChannel.getMyRole() == Member.Role.OPERATOR) {
            // Mute a user.
            groupChannel.muteUser(USER, new groupChannel.GroupChannelMuteHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {
                        // Handle error.
                    }

                    // The user is successfully muted in the channel.
                    // You could notify the user of being muted by displaying a prompt.
                    ...
                }
            });

            // Unmute a user.
            groupChannel.unmuteUser(USER, new GroupChannel.GroupChannelUnmuteHandler() {
                @Override
                public void onResult(SendBirdException e) {
                    if (e != null) {
                        // Handle error.
                    }

                    // The user is successfully unmuted in the channel.
                    // You could notify the user of being unmuted by displaying a prompt.
                    ...
                }
            });
        }
    }
});

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


Report a message, a user, or a channel

Copy link

In a group channel, a user can report suspicious or harassing 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.

// Reporting a message.
groupChannel.reportMessage(MESSAGE_TO_REPORT, REPORT_CATEGORY, DESCRIPTION, new BaseChannel.ReportMessageHandler() {
    @Override
    public void onResult(SendBirdException e) {
        if (e != null) {
            // Handle error.
        }

        ...
    }
});

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

        ...
    }
});

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

        ...
    }
});

List of arguments

Copy link
ArgumentTypeDescription

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.