Messaging
ConnectyCube Chat (messaging) API is built on top of Real-time(XMPP) protocol. In order to use it you need to setup real-time connection with ConnectyCube Chat server and use it to exchange data.
By default Real-time Chat works over secure TLS connection.
Get started with SDK
Follow the Getting Started guide on how to connect ConnectyCube SDK and start building your first app.
Code samples
There are ready-to-go FREE code samples to help you better understand how to integrate messaging capabilities in your apps:
Connect to chat
SDK v2 kotlin
val user = ConnectycubeUser().apply {
id = 21
password = "supersecurepwd"
}
// or just
val user = user {
id = 21
password = "supersecurepwd"
}
ConnectyCube.chat.login(user, {}, { ex -> Log.d(tag, "login ex= $ex") })
SDK v1 kotlin
// Provide chat connection configuration
val chatServiceConfigurationBuilder = ConfigurationBuilder().apply {
socketTimeout = 60
isKeepAlive = true
isUseTls = true //By default TLS is disabled.
}
ConnectycubeChatService.setConnectionFabric(TcpChatConnectionFabric(chatServiceConfigurationBuilder))
val chatService = ConnectycubeChatService.getInstance()
val user = ConnectycubeUser().apply {
id = 21
password = "supersecurepwd"
}
chatService.login(user, object : EntityCallback<Void?> {
override fun onError(error: ResponseException) {
}
override fun onSuccess(result: Void?, args: Bundle) {
}
})
SDK v1 java
// Provide chat connection configuration
ConnectycubeChatService.ConfigurationBuilder chatServiceConfigurationBuilder = new ConnectycubeChatService.ConfigurationBuilder();
chatServiceConfigurationBuilder.setSocketTimeout(60);
chatServiceConfigurationBuilder.setKeepAlive(true);
chatServiceConfigurationBuilder.setUseTls(true); //By default TLS is disabled.
ConnectycubeChatService.setConfigurationBuilder(chatServiceConfigurationBuilder);
ConnectycubeChatService chatService = ConnectycubeChatService.getInstance();
final ConnectycubeUser user = new ConnectycubeUser();
user.setId(21);
user.setPassword("supersecurepwd");
chatService.login(user, new EntityCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(ResponseException errors) {
}
});
Use ConnectionListener to handle different connection states:
SDK v2 kotlin
ConnectyCube.chat.addConnectionListener(object : ConnectycubeConnectionListener {
override fun onConnected() {
}
override fun onDisconnected() {
}
})
SDK v1 kotlin
val connectionListener: ConnectionListener = object : ConnectionListener {
override fun connected(connection: XMPPConnection) {
}
override fun connectionClosed() {
}
override fun connectionClosedOnError(e: Exception) {
}
override fun reconnectingIn(seconds: Int) {
}
override fun reconnectionSuccessful() {
}
override fun authenticated(connection: XMPPConnection, resumed: Boolean) {
}
override fun reconnectionFailed(e: Exception) {
}
}
ConnectycubeChatService.getInstance().addConnectionListener(connectionListener)
SDK v1 java
ConnectionListener connectionListener = new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
}
@Override
public void authenticated(XMPPConnection connection) {
}
@Override
public void connectionClosed() {
}
@Override
public void connectionClosedOnError(Exception e) {
}
@Override
public void reconnectingIn(int seconds) {
}
@Override
public void reconnectionSuccessful() {
}
@Override
public void reconnectionFailed(Exception e) {
}
};
ConnectycubeChatService.getInstance().addConnectionListener(connectionListener);
Connect to chat using custom authentication providers
In some cases we don't have a user's password, for example when login via:
- Firebase phone authorization
- Custom identity authentication
- etc.
In such cases ConnectyCube API provides possibility to use ConnectyCube session token as a password for chat connection:
SDK v2 kotlin
val token = ConnectycubeSessionManager.getToken()
val user = ConnectycubeUser().apply {
id = 21
password = token
}
SDK v1 kotlin
// get current ConnectyCube session token and set as user's password
val token = ConnectycubeSessionManager.getInstance().token
val user = ConnectycubeUser().apply {
id = 21
password = token
}
SDK v1 java
// get current ConnectyCube session token and set as user's password
String token = ConnectycubeSessionManager.getInstance().getToken();
final ConnectycubeUser user = new ConnectycubeUser();
user.setId(21);
user.setPassword(token);
Disconnect
To logout from chat connection use logout method:
SDK v2 kotlin
val isLoggedIn = ConnectyCube.chat.isLoggedIn()
if (!isLoggedIn) {
return
}
ConnectyCube.chat.logout({}, { ex -> Log.d(tag, "logout ex= $ex") })
SDK v1 kotlin
val isLoggedIn = chatService.isLoggedIn
if (!isLoggedIn) {
return
}
chatService.logout(object : EntityCallback<Void?> {
override fun onError(error: ResponseException) {
}
override fun onSuccess(result: Void?, args: Bundle) {
}
})
SDK v1 java
boolean isLoggedIn = chatService.isLoggedIn();
if(!isLoggedIn){
return;
}
chatService.logout(new EntityCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(ResponseException errors) {
}
});
To fully destroy chat connection use destroy method:
SDK v2 kotlin
ConnectyCube.chat.destroy()
SDK v1 kotlin
chatService.destroy()
SDK v1 java
chatService.destroy();
Reconnection
The SDK reconnects automatically when connection to Chat server is lost.
There is a way to disable it and then manage it manually:
SDK v2 kotlin
//Coming soon
SDK v1 kotlin
ConnectycubeChatService.getInstance().isReconnectionAllowed = false
SDK v1 java
ConnectycubeChatService.getInstance().setReconnectionAllowed(false);
Dialogs
All chats between users are organized in dialogs. The are 4 types of dialogs:
- 1-1 chat - a conversation between 2 users.
- group chat - a conversation between specified list of users.
- public chat - an open conversation. Any user from your app can subscribe to it.
- broadcast - chat where a message is sent to all users within application at once. All the users from the application are able to join this group. Broadcast dialogs can be created only via Admin panel.
You need to create a new dialog and then use it to chat with other users. You also can obtain a list of your existing dialogs.
Create new dialog
Create 1-1 chat
You need to pass ConnectycubeDialogType.PRIVATE
as a type and an id of an opponent you want to create a chat with:
SDK v2 kotlin
val dialog = ConnectycubeDialog(type = ConnectycubeDialogType.PRIVATE, occupantsIds = occupantIds)
ConnectyCube.createDialog(cubeDialog, { dialog ->
}, { error ->
})
SDK v1 kotlin
val occupantIds = ArrayList<Int>().apply {
add(34)
}
val dialog = ConnectycubeChatDialog().apply {
type = ConnectycubeDialogType.PRIVATE
setOccupantsIds(occupantIds)
}
// or just use DialogUtils
// val dialog = DialogUtils.buildPrivateDialog(34)
ConnectycubeRestChatService.createChatDialog(dialog)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(createdDialog: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(exception: ResponseException) {
}
})
SDK v1 java
ArrayList<Integer> occupantIds = new ArrayList<Integer>();
occupantIds.add(34);
ConnectycubeChatDialog dialog = new ConnectycubeChatDialog();
dialog.setType(ConnectycubeDialogType.PRIVATE);
dialog.setOccupantsIds(occupantIds);
//or just use DialogUtils
//ConnectycubeChatDialog dialog = DialogUtils.buildPrivateDialog(recipientId);
ConnectycubeRestChatService.createChatDialog(dialog).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog createdDialog, Bundle params) {
}
@Override
public void onError(ResponseException exception) {
}
});
Create group chat
You need to pass ConnectycubeDialogType.GROUP
as a type and ids of opponents you want to create a chat with:
SDK v2 kotlin
val dialog = ConnectycubeDialog( type = ConnectycubeDialogType.GROUP, name = "Hawaii party", occupantsIds = occupantIds)
ConnectyCube.createDialog(cubeDialog, { dialog ->
}, { error ->
})
SDK v1 kotlin
val occupantIds = ArrayList<Int>().apply {
add(34)
add(35)
add(36)
}
val dialog = ConnectycubeChatDialog().apply {
type = ConnectycubeDialogType.GROUP
name = "Hawaii party"
// photo = "..."
// description = "..."
setOccupantsIds(occupantIds)
}
//or just use DialogUtils
//val dialog = DialogUtils.buildDialog("Hawaii party", ConnectycubeDialogType.GROUP, occupantIds).apply {
// photo = "..."
// description = "..."
//}
ConnectycubeRestChatService.createChatDialog(dialog)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(createdDialog: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(exception: ResponseException) {
}
})
SDK v1 java
ArrayList<Integer> occupantIds = new ArrayList<Integer>();
occupantIds.add(34);
occupantIds.add(35);
occupantIds.add(36);
ConnectycubeChatDialog dialog = new ConnectycubeChatDialog();
dialog.setType(ConnectycubeDialogType.GROUP);
dialog.setOccupantsIds(occupantIds);
dialog.setName("Hawaii party");
//dialog.setPhoto("...");
//dialog.setDescription("...");
//or just use DialogUtils
//ConnectycubeChatDialog dialog = DialogUtils.buildDialog("Hawaii party", ConnectycubeDialogType.GROUP, occupantIds);
ConnectycubeRestChatService.createChatDialog(dialog).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog createdDialog, Bundle params) {
}
@Override
public void onError(ResponseException exception) {
}
});
Create public chat
It's possible to create a public chat, so any user from your application can subscribe to it.
You need to pass ConnectycubeDialogType.PUBLIC
as a type to create a chat with:
SDK v2 kotlin
val dialog = ConnectycubeDialog(type = ConnectycubeDialogType.PUBLIC, name = "Blockchain trends")
ConnectyCube.createDialog(cubeDialog, { dialog ->
}, { error ->
})
SDK v1 kotlin
val dialog = ConnectycubeChatDialog().apply {
type = ConnectycubeDialogType.PUBLIC
name = "Blockchain trends"
// photo = "..."
// description = "..."
}
ConnectycubeRestChatService.createChatDialog(dialog)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(createdDialog: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(exception: ResponseException) {
}
})
SDK v1 java
ConnectycubeChatDialog dialog = new ConnectycubeChatDialog();
dialog.setType(ConnectycubeDialogType.PUBLIC);
dialog.setName("Blockchain trends");
//dialog.setPhoto("...");
//dialog.setDescription("...");
ConnectycubeRestChatService.createChatDialog(dialog).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog createdDialog, Bundle params) {
}
@Override
public void onError(ResponseException exception) {
}
});
With public dialog ID any a user can subscribe to the public dialog via the following code:
SDK v2 kotlin
ConnectyCube.subscribeToDialog(dialogId, { dialog ->
}, { error ->
})
SDK v1 kotlin
ConnectycubeRestChatService.subscribePublicDialog(dialogID)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(dialog: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
ConnectycubeRestChatService.subscribePublicDialog(dialogID).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog dialog, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
After dialog subscription, this dialog will be listed in retrieve dialogs request and you also will be able to chat in it.
You also can unsubscribe if you do not want to be in this public dialog anymore:
SDK v2 kotlin
ConnectyCube.unSubscribeFromDialog(dialogId, {
}, { error ->
})
SDK v1 kotlin
ConnectycubeRestChatService.unsubscribePublicDialog(dialogID)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(result: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
ConnectycubeRestChatService.unsubscribePublicDialog(dialogID).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog result, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
Retrieve list of dialogs
It's common to request all your conversations on every app login:
SDK v2 kotlin
val params: HashMap<String, Any> = hashMapOf(
"limit" to 50,
"skip" to 100
)
ConnectyCube.getDialogs(params, successCallback = { resultDialogs ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val requestBuilder = RequestGetBuilder().apply {
limit = 50
skip = 100
// sortAsc(Consts.DIALOG_LAST_MESSAGE_DATE_SENT_FIELD_NAME)
}
ConnectycubeRestChatService.getChatDialogs(null as ConnectycubeDialogType, requestBuilder)
.performAsync(object : EntityCallback<ArrayList<ConnectycubeChatDialog>> {
override fun onSuccess(dialogs: ArrayList<ConnectycubeChatDialog>, params: Bundle) {
val totalEntries = params.getInt(Consts.TOTAL_ENTRIES)
}
override fun onError(exception: ResponseException) {
}
})
SDK v1 java
RequestGetBuilder requestBuilder = new RequestGetBuilder();
requestBuilder.setLimit(50);
requestBuilder.setSkip(100);
//requestBuilder.sortAsc(Consts.DIALOG_LAST_MESSAGE_DATE_SENT_FIELD_NAME);
ConnectycubeRestChatService.getChatDialogs((ConnectycubeDialogType)null, requestBuilder).performAsync(new EntityCallback<ArrayList<ConnectycubeChatDialog>>() {
@Override
public void onSuccess(ArrayList<ConnectycubeChatDialog> dialogs, Bundle params) {
int totalEntries = params.getInt(Consts.TOTAL_ENTRIES);
}
@Override
public void onError(ResponseException exception) {
}
});
It will return all your 1-1 dialogs, group dialog and also public dialogs your are subscribed to.
If you want to retrieve only conversations updated after some specific date time, you can use requestBuilder.gt("updated_at", "1455098137");
filter. This is useful if you cache conversations somehow and do not want to obtain the whole list of your conversations on every app start.
Update dialog’s name, description, photo
User can update group chat name, description, photo:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val params = UpdateDialogParams() //class-helper to simple config search request
params.newName = "Hawaii party"
params.newPhoto = "https://new_photo_url"
params.newDescription = "New dialog description"
ConnectyCube.updateDialog(dialogId, params.getUpdateDialogParams(), successCallback = { resultDialog ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val dialog = ConnectycubeChatDialog().apply {
dialogId = "5356c64ab35c12bd3b108a41"
name = "Hawaii party"
photo = "https://new_photo_url" // or it can be an ID to some file in Storage module
description = "New dialog description"
}
ConnectycubeRestChatService.updateChatDialog(dialog, null)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(updatedDialog: ConnectycubeChatDialog, bundle: Bundle) {
}
override fun onError(error: ResponseException) {
}
})
SDK v1 java
ConnectycubeChatDialog dialog = new ConnectycubeChatDialog();
dialog.setDialogId("5356c64ab35c12bd3b108a41");
dialog.setName("Hawaii party");
dialog.setPhoto("https://new_photo_url"); // or it can be an ID to some file in Storage module
dialog.setDescription("New dialog description");
ConnectycubeRestChatService.updateChatDialog(dialog, null).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog updatedDialog, Bundle bundle) {
}
@Override
public void onError(ResponseException error) {
}
});
Add/Remove occupants
You can add/remove occupants in group and public dialogs:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val params = UpdateDialogParams()
params.addOccupantIds = hashSetOf(378)
// params.deleteOccupantIds = hashSetOf(22)
ConnectyCube.updateDialog(dialogId, params.getUpdateDialogParams(), successCallback = { resultDialog ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val requestBuilder = DialogRequestBuilder().apply {
addUsers(378)
// removeUsers(22)
}
val dialog = ConnectycubeChatDialog("5356c64ab35c12bd3b108a41")
ConnectycubeRestChatService.updateChatDialog(dialog, requestBuilder)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(updatedDialog: ConnectycubeChatDialog, bundle: Bundle) {
}
override fun onError(error: ResponseException) {
}
})
SDK v1 java
DialogRequestBuilder requestBuilder = new DialogRequestBuilder();
requestBuilder.addUsers(378);
// requestBuilder.removeUsers(22);
ConnectycubeChatDialog dialog = new ConnectycubeChatDialog();
dialog.setDialogId("5356c64ab35c12bd3b108a41");
ConnectycubeRestChatService.updateChatDialog(dialog, requestBuilder).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog updatedDialog, Bundle bundle) {
}
@Override
public void onError(ResponseException error) {
}
});
Important note: Only group chat owner and admins can remove other users from group chat.
Add/Remove admins
Admins it's a special role in chats. They have the same permissions as a dialog's creator except add/remove other admins and remove dialog.
Owner of the group chat dialog can add admins:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val params = UpdateDialogParams()
params.addAdminIds = hashSetOf(17616, 17617)
ConnectyCube.updateDialog(dialogId, params.getUpdateDialogParams(), successCallback = { resultDialog ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val updateBuilder = DialogRequestBuilder().apply {
addAdminsIds(17616, 17617)
}
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(result: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
DialogRequestBuilder updateBuilder = new DialogRequestBuilder();
updateBuilder.addAdminsIds(17616, 17617);
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog result, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
and remove:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val params = UpdateDialogParams()
params.deleteAdminIds = hashSetOf(17616, 17617)
ConnectyCube.updateDialog(dialogId, params.getUpdateDialogParams(), successCallback = { resultDialog ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val updateBuilder = DialogRequestBuilder().apply {
removeAdminsIds(17616, 17617)
}
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(result: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
DialogRequestBuilder updateBuilder = new DialogRequestBuilder();
updateBuilder.removeAdminsIds(17616, 17617);
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog result, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
Pin messages
Pinning a message allows group owner or chat admins to easily store messages which are important, so that all users in chat have a quick access to them. The following code pins some messages to a particular group dialog:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val params = UpdateDialogParams()
params.addPinnedMsgIds = hashSetOf("5356c64ab35c12bd3b10ba32", "5356c64ab35c12bd3b10wa65")
// params.deletePinnedMsgIds = hashSetOf("5356c64ab35c12bd3b10ba32", "5356c64ab35c12bd3b10wa65")
ConnectyCube.updateDialog(dialogId, params.getUpdateDialogParams(), successCallback = { resultDialog ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val updateBuilder = DialogRequestBuilder().apply {
addPinnedMessagesIds(
"5356c64ab35c12bd3b10ba32",
"5356c64ab35c12bd3b10wa65"
)
// removePinnedMessagesIds(
// "5356c64ab35c12bd3b10ba32",
// "5356c64ab35c12bd3b10wa65"
// )
}
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder)
.performAsync(object : EntityCallback<ConnectycubeChatDialog> {
override fun onSuccess(result: ConnectycubeChatDialog, params: Bundle) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
DialogRequestBuilder updateBuilder = new DialogRequestBuilder();
updateBuilder.addPinnedMessagesIds("5356c64ab35c12bd3b10ba32", "5356c64ab35c12bd3b10wa65");
//updateBuilder.removePinnedMessagesIds("5356c64ab35c12bd3b10ba32", "5356c64ab35c12bd3b10wa65");
ConnectycubeRestChatService.updateChatDialog(groupDialog, updateBuilder).performAsync(new EntityCallback<ConnectycubeChatDialog>() {
@Override
public void onSuccess(ConnectycubeChatDialog result, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
Remove dialog
The following snippet is used to delete a conversation:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val forceDelete = false
ConnectyCube.deleteDialog(dialogId, forceDelete, successCallback = { },
errorCallback = { })
SDK v1 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val forceDelete = false
ConnectycubeRestChatService.deleteDialog(dialogId, forceDelete)
.performAsync(object : EntityCallback<Void?> {
override fun onSuccess(aVoid: Void?, bundle: Bundle) {
}
override fun onError(error: ResponseException) {
}
})
SDK v1 java
String dialogId = "5356c64ab35c12bd3b108a41";
boolean forceDelete = false;
ConnectycubeRestChatService.deleteDialog(dialogId, forceDelete).performAsync(new EntityCallback<Void>() {
@Override
public void onSuccess(Void aVoid, Bundle bundle) {
}
@Override
public void onError(ResponseException error) {
}
});
This request will remove this conversation for current user, but other users still will be able to chat there.
The forceDelete
parameter is used to completely remove the dialog. Only group chat owner can remove the group conversation for all users.
You can also delete multiple conversations in a single request.
Chat history
Every chat conversation stores its chat history which you can retrieve:
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val messageGetBuilder: GetMessagesParameters = GetMessagesParameters().also { it.limit = 100; it.markAsRead = false; it.sorter = RequestSorter("", "date_sent", "desc")}
ConnectyCube.getMessages(dialogId, messageGetBuilder.getRequestParameters(), successCallback = { pagedMessagesResult ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val chatDialog = ConnectycubeChatDialog("5356c64ab35c12bd3b108a41")
val messageGetBuilder = MessageGetBuilder().apply {
limit = 100
// gt(Consts.MESSAGE_DATE_SENT, "1455098137")
}
ConnectycubeRestChatService.getDialogMessages(chatDialog, messageGetBuilder)
.performAsync(object : EntityCallback<ArrayList<ConnectycubeChatMessage>> {
override fun onSuccess(messages: ArrayList<ConnectycubeChatMessage>, bundle: Bundle) {
}
override fun onError(error: ResponseException) {
}
})
SDK v1 java
ConnectycubeChatDialog chatDialog = new ConnectycubeChatDialog("5356c64ab35c12bd3b108a41");
MessageGetBuilder messageGetBuilder = new MessageGetBuilder();
messageGetBuilder.setLimit(100);
// messageGetBuilder.gt("date_sent", "1455098137");
ConnectycubeRestChatService.getDialogMessages(chatDialog, messageGetBuilder).performAsync(new EntityCallback<ArrayList<ConnectycubeChatMessage>>() {
@Override
public void onSuccess(ArrayList<ConnectycubeChatMessage> messages, Bundle bundle) {
}
@Override
public void onError(ResponseException error) {
}
});
If you want to retrieve chat messages that were sent after or before specific date time only, you can use messageGetBuilder.gt("date_sent", "1455098137")
or messageGetBuilder.lt("date_sent", "1455098137")
filter. This is useful if you implement pagination for loading messages in your app.
Important note: All retrieved chat messages will be marked as read after the request. If you decided not to mark chat messages as read, then add the following parameter to your request: messageGetBuilder.markAsRead(false);
Send/Receive chat messages
Receive messages
There is IncomingMessagesManager
to listen for all incoming messages from all dialogs.
SDK v2 kotlin
ConnectyCube.chat.addMessageListener(object: ConnectycubeMessageListener {
override fun onError(message: ConnectycubeMessage, ex: Throwable) {
}
override fun onMessage(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
val incomingMessagesManager = chatService.incomingMessagesManager
incomingMessagesManager.addDialogMessageListener(object : ChatDialogMessageListener {
override fun processMessage(dialogId: String,
message: ConnectycubeChatMessage,
senderId: Int)
{
}
override fun processError(dialogId: String,
exception: ChatException,
message: ConnectycubeChatMessage,
senderId: Int)
{
}
})
SDK v1 java
IncomingMessagesManager incomingMessagesManager = chatService.getIncomingMessagesManager();
incomingMessagesManager.addDialogMessageListener(new ChatDialogMessageListener() {
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
@Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
}
});
Pay attention, messages from group & public chat dialogs will be received in this callback only after you join the dialogs.
Pay attention, before using dialog you need to init it for ConnectycubeChatService. Call this once you've got dialog -
chatDialog.initForChat(ConnectycubeChatService.getInstance())
.
1-1 chat
SDK v2 kotlin
ConnectyCube.chat.addMessageListener(object: ConnectycubeMessageListener {
override fun onError(message: ConnectycubeMessage, ex: Throwable) {
}
override fun onMessage(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
val privateDialog = ...
val chatMessage = ConnectycubeChatMessage().apply {
body = "How are you today?"
setSaveToHistory(true)
}
privateDialog.sendMessage(chatMessage)
privateDialog.addMessageListener(object: ChatDialogMessageListener {
override fun processMessage(dialogId: String,
message: ConnectycubeChatMessage,
senderId: Int
) {
}
override fun processError(dialogId: String,
exception: ChatException,
message: ConnectycubeChatMessage,
senderId: Int?
) {
}
})
SDK v1 java
try {
ConnectycubeChatDialog privateDialog = ...;
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setBody("How are you today?");
chatMessage.setSaveToHistory(true);
privateDialog.sendMessage(chatMessage);
} catch (SmackException.NotConnectedException e) {
}
privateDialog.addMessageListener(new ChatDialogMessageListener() {
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
@Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
}
});
Group/Public chat
Before you start chatting in a group/public conversation, you need to join it by calling join
method:
SDK v1 kotlin
val groupChatDialog = ...
groupChatDialog.join(object : EntityCallback<Void?> {
override fun onSuccess(result: Void?, args: Bundle?) {
}
override fun onError(exception: ResponseException) {
}
})
SDK v1 java
ConnectycubeChatDialog groupChatDialog = ...;
groupChatDialog.join(new EntityCallback() {
@Override
public void onSuccess(Object o, Bundle bundle) {
}
@Override
public void onError(ResponseException e) {
}
});
Then you are able to send/receive messages:
SDK v2 kotlin
val chatMessage = ConnectycubeMessage()
chatMessage.dialogId = dialogId
chatMessage.saveToHistory = true
chatMessage.dateSent = System.currentTimeMillis() / 1000
chatMessage.markable = true
if(dialog.type == ConnectycubeDialogType.PRIVATE) chatMessage.recipientId = dialog.getRecipientId()
else chatMessage.type = when (dialog.type) {
ConnectycubeDialogType.GROUP, ConnectycubeDialogType.PUBLIC -> ConnectycubeMessageType.Groupchat
else -> ConnectycubeMessageType.Chat
}
chatMessage.body = "How are you today?"
ConnectyCube.chat.sendMessage(chatMessage)
ConnectyCube.chat.addMessageListener(object: ConnectycubeMessageListener {
override fun onError(message: ConnectycubeMessage, ex: Throwable) {
}
override fun onMessage(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
val chatMessage = ConnectycubeChatMessage().apply {
body = "How are you today?"
setSaveToHistory(true)
}
groupChatDialog.sendMessage(chatMessage)
groupChatDialog.addMessageListener(object : ChatDialogMessageListener {
override fun processMessage(dialogId: String,
message: ConnectycubeChatMessage,
senderId: Int
) {
}
override fun processError(dialogId: String,
exception: ChatException,
message: ConnectycubeChatMessage,
senderId: Int
) {
}
})
SDK v1 java
try {
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setBody("How are you today?");
chatMessage.setSaveToHistory(true);
groupChatDialog.sendMessage(chatMessage);
} catch (SmackException.NotConnectedException e) {
}
groupChatDialog.addMessageListener(new ChatDialogMessageListener() {
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
@Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
}
});
When it's done, you can leave the group conversation by calling leave
method:
SDK v1 kotlin
groupChatDialog.leave()
SDK v1 java
try {
groupChatDialog.leave();
groupChatDialog = null;
} catch (XMPPException | SmackException.NotConnectedException e) {
}
'Sent' status
There is a 'sent' status to ensure that message is delivered to the server.
In order to use the feature you need to enable it:
SDK v1 kotlin
val chatService = ConnectycubeChatService.getInstance()
chatService.setUseStreamManagement(true)
chatService.login(user)
SDK v1 java
ConnectycubeChatService chatService = ConnectycubeChatService.getInstance();
chatService.setUseStreamManagement(true);
chatService.login(user);
Pay attention: you should enable Stream Management before logging into the chat. Stream Management is initialized only during chat login step.
The Stream Management defines an extension for active management of a stream between client and server, including features for stanza acknowledgements.
The following callback is used to track the status:
SDK v2 kotlin
ConnectyCube.chat.addMessageSentListener(object: ConnectycubeMessageSentListener {
override fun onMessageSent(message: ConnectycubeMessage) {
}
override fun onMessageSentFailed(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
val messageSentListener = object : ChatDialogMessageSentListener {
override fun processMessageSent(dialogId: String,
message: ConnectycubeChatMessage
) {
}
override fun processMessageFailed(dialogId: String,
message: ConnectycubeChatMessage
) {
}
}
val chatDialog = ...
chatDialog.addMessageSentListener(messageSentListener)
SDK v1 java
ChatDialogMessageSentListener messageSentListener = new ChatDialogMessageSentListener() {
@Override
public void processMessageSent(String dialogId, ConnectycubeChatMessage message) {
}
@Override
public void processMessageFailed(String dialogId, ConnectycubeChatMessage message) {
}
};
ConnectycubeChatDialog chatDialog = ...;
chatDialog.addMessageSentListener(messageSentListener);
'Delivered' status
The following callback is used to track the 'delivered' status:
SDK v2 kotlin
ConnectyCube.chat.addMessageStatusListener(object: ConnectycubeMessageStatusListener {
override fun onMessageDelivered(message: ConnectycubeMessage) {
}
override fun onMessageRead(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
// call it after chat login
val messageStatusesManager: MessageStatusesManager = ConnectycubeChatService.getInstance().messageStatusesManager
val messageStatusListener = object : MessageStatusListener {
override fun processMessageDelivered(messageId: String,
dialogId: String,
userId: Int
) {
}
override fun processMessageRead(messageId: String,
dialogId: String,
userId: Int
) {
}
}
messageStatusesManager.addMessageStatusListener(messageStatusListener)
SDK v1 java
private MessageStatusesManager messageStatusesManager;
private MessageStatusListener messageStatusListener;
// call it after chat login
messageStatusesManager = ConnectycubeChatService.getInstance().getMessageStatusesManager();
messageStatusListener = new MessageStatusListener() {
@Override
public void processMessageDelivered(String messageId, String dialogId, Integer userId) {
}
@Override
public void processMessageRead(String messageId, String dialogId, Integer userId) {
}
};
messageStatusesManager.addMessageStatusListener(messageStatusListener);
The SDK sends the 'delivered' status automatically when the message is received by the recipient.
This is controlled by chatMessage.setMarkable(true)
parameter when you send a message.
If markable
is false
or omitted, then you can send the delivered status manually via Chat:
SDK v2 kotlin
val chatDialog = ...
val message = ...
ConnectyCube.chat.sendDeliveredStatus(message)
SDK v1 kotlin
val chatDialog = ...
val message = ...
chatDialog.deliverMessage(message)
SDK v1 java
ConnectycubeChatMessage message = ...;
try {
chatDialog.deliverMessage(message);
} catch (XMPPException | SmackException.NotConnectedException e) {
}
and via REST
SDK v2 kotlin
val updatedParams = UpdateMessageParameters().also { it.delivered = true }
ConnectyCube.updateMessage(messageId, dialogId, updatedParams.getRequestParameters(), {
}, { error ->
})
SDK v1 kotlin
val messageUpdateBuilder = MessageUpdateBuilder().apply {
markDelivered()
}
ConnectycubeRestChatService.updateMessage(messageId, dialogId, messageUpdateBuilder)
.performAsync(object : EntityCallback<Void?> {
override fun onSuccess(result: Void?, params: Bundle?) {
}
override fun onError(responseException: ResponseException) {
}
})
SDK v1 java
MessageUpdateBuilder messageUpdateBuilder = new MessageUpdateBuilder();
messageUpdateBuilder.markDelivered();
ConnectycubeRestChatService.updateMessage(messageId, dialogId, messageUpdateBuilder).performAsync(new EntityCallback<Void>() {
@Override
public void onSuccess(Void result, Bundle params) {
}
@Override
public void onError(ResponseException responseException) {
}
});
'Read' status
Send the 'read' status:
SDK v2 kotlin
ConnectyCube.chat.sendReadStatus(message)
SDK v1 kotlin
chatDialog.readMessage(chatMessage)
SDK v1 java
try {
chatDialog.readMessage(chatMessage);
} catch (XMPPException | SmackException.NotConnectedException e) {
}
Receive the 'read' status callback:
SDK v2 kotlin
ConnectyCube.chat.addMessageStatusListener(object: ConnectycubeMessageStatusListener {
override fun onMessageDelivered(message: ConnectycubeMessage) {
}
override fun onMessageRead(message: ConnectycubeMessage) {
}
})
SDK v1 kotlin
// call it after chat login
val messageStatusesManager = ConnectycubeChatService.getInstance().messageStatusesManager
val messageStatusListener = object : MessageStatusListener {
override fun processMessageDelivered(messageId: String,
dialogId: String,
userId: Int
) {
}
override fun processMessageRead(messageId: String,
dialogId: String,
userId: Int
) {
}
}
messageStatusesManager.addMessageStatusListener(messageStatusListener)
SDK v1 java
private MessageStatusesManager messageStatusesManager;
private MessageStatusListener messageStatusListener;
// call it after chat login
messageStatusesManager = ConnectycubeChatService.getInstance().getMessageStatusesManager();
messageStatusListener = new MessageStatusListener() {
@Override
public void processMessageDelivered(String messageId, String dialogId, Integer userId) {
}
@Override
public void processMessageRead(String messageId, String dialogId, Integer userId) {
}
};
messageStatusesManager.addMessageStatusListener(messageStatusListener);
'Is typing' status
The following 'typing' notifications are supported:
- typing: The user is composing a message. The user is actively interacting with a message input interface specific to this chat session (e.g., by typing in the input area of a chat window)
- stopped: The user had been composing but now has stopped. The user has been composing but has not interacted with the message input interface for a short period of time (e.g., 30 seconds)
Send the 'is typing' status:
SDK v2 kotlin
ConnectyCube.chat.sendIsTypingStatus(chatDialog)
...
ConnectyCube.chat.sendStopTypingStatus(chatDialog)
SDK v1 kotlin
chatDialog.sendIsTypingNotification()
...
chatDialog.sendStopTypingNotification()
SDK v1 java
try {
chatDialog.sendIsTypingNotification();
} catch (XMPPException | SmackException.NotConnectedException e) {
e.printStackTrace();
}
...
try {
chatDialog.sendStopTypingNotification();
} catch (XMPPException | SmackException.NotConnectedException e) {
e.printStackTrace();
}
Receive the 'is typing' status callback:
SDK v2 kotlin
ConnectyCube.chat.addTypingStatusListener(object: ConnectycubeChatTypingListener {
override fun onUserIsTyping(dialogId: String?, userId: Int) {
}
override fun onUserStopTyping(dialogId: String?, userId: Int) {
}
})
SDK v1 kotlin
val typingListener = object : ChatDialogTypingListener {
override fun processUserIsTyping(dialogId: String, senderId: Int) {
}
override fun processUserStopTyping(dialogId: String, senderId: Int) {
}
}
chatDialog.addIsTypingListener(typingListener)
SDK v1 java
ChatDialogTypingListener typingListener = new ChatDialogTypingListener() {
@Override
public void processUserIsTyping(String dialogId, Integer senderId) {
}
@Override
public void processUserStopTyping(String dialogId, Integer senderId) {
}
};
chatDialog.addIsTypingListener(typingListener);
Edit Message
The following snippet is used to edit chat message:
SDK v1 kotlin
chatDialog.editMessageWithId("5356c64ab35c12bd3b10wa64", "Updated message body", true)
SDK v1 java
try {
dialog.editMessageWithId("5356c64ab35c12bd3b10wa64", "Updated message body", true);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
Other users will receive the 'update' status callback:
SDK v1 kotlin
val messageUpdateListener = MessageUpdateListener { messageID, dialogId, newBody, isLastMessage ->
}
ConnectycubeChatService.getInstance().messageStatusesManager.addMessageUpdateListener(messageUpdateListener)
SDK v1 java
MessageUpdateListener messageUpdateListener = new MessageUpdateListener() {
@Override
public void processMessageUpdated(String messageID, String dialogId, String newBody, boolean isLastMessage) {
}
};
ConnectycubeChatService.getInstance().getMessageStatusesManager().addMessageUpdateListener(messageUpdateListener);
Delete chat messages
The following snippet is used to remove chat message via REST:
SDK v2 kotlin
val messagesIds = listOf("546cc3240eda8f2dd7ee2291", "546cc3230eda8f2dd7ee2292")
ConnectyCube.deleteMessages(messagesIds, true, successCallback = { deleteResult ->
}, errorCallback = { error ->
})
SDK v1 kotlin
val messagesIds = HashSet<String>().apply {
add("546cc3240eda8f2dd7ee2291")
add("546cc3230eda8f2dd7ee2292")
}
val forceDelete = false
ConnectycubeRestChatService.deleteMessages(messagesIds, forceDelete)
.performAsync(object : EntityCallback<Void?> {
override fun onSuccess(aVoid: Void?, bundle: Bundle?) {
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
Set<String> messagesIds = new HashSet<String>() {{
add("546cc3240eda8f2dd7ee2291");
add("546cc3230eda8f2dd7ee2292");
}};
boolean forceDelete = false;
ConnectycubeRestChatService.deleteMessages(messagesIds, forceDelete).performAsync(new EntityCallback<Void>() {
@Override
public void onSuccess(Void aVoid, Bundle bundle) {
}
@Override
public void onError(ResponseException e) {
}
});
This request will remove the messages from current user history only, without affecting the history of other users.
The forceDelete
parameter is used to completely remove messages.
The following snippet is used to remove chat message in a real time:
SDK v1 kotlin
chatDialog.removeMessageWithId("5356c64ab35c12bd3b10wa64")
SDK v1 java
try {
dialog.removeMessageWithId("5356c64ab35c12bd3b10wa64");
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
Other users will receive the 'delete' status callback:
SDK v1 kotlin
val messageDeleteListener = MessageDeleteListener { messageID, dialogId ->
//actions after success deleting message
}
ConnectycubeChatService.getInstance().messageStatusesManager.addMessageDeleteListener(messageDeleteListener)
SDK v1 java
MessageDeleteListener messageDeleteListener = new MessageDeleteListener() {
@Override
public void processMessageDeleted(String messageID, String dialogId) {
//actions after success deleting message
}
};
ConnectycubeChatService.getInstance().getMessageStatusesManager().addMessageDeleteListener(messageDeleteListener);
Self-destroy message
Self-destroy messages is used if you want to implement some sort of Secret Chat where messages are visible only for some limited amount of time.
It's your responsibility to setup a timer in your app and remove messages from the client side.
Self-destroy messages are not stored in server history.
SDK v1 kotlin
val chatMessage = ConnectycubeChatMessage().apply {
body = "Self destroy message"
destroyAfter = 10
}
chatDialog.sendMessage(chatMessage)
chatDialog.addMessageListener(object : ChatDialogMessageListener {
override fun processMessage(dialogId: String,
message: ConnectycubeChatMessage,
senderId: Int
) {
if (message.destroyAfter > 0) {
// setup a timer
}
}
override fun processError(dialogId: String,
exception: ChatException,
message: ConnectycubeChatMessage,
senderId: Int
) {
}
})
SDK v1 java
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setBody("Self destroy message");
chatMessage.setDestroyAfter(10);
try {
chatDialog.sendMessage(chatMessage);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
chatDialog.addMessageListener(new ChatDialogMessageListener() {
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
if (message.getDestroyAfter() > 0) {
// setup a timer
}
}
});
Attachments
Image/Video
Chat attachments are supported with the cloud storage API. In order to send a chat attachment you need to upload the file to ConnectyCube cloud storage and obtain a link to the file (file UID). Then you need to include this UID into chat message and send it.
SDK v2 kotlin
val messageAttachment = File("some_image.png")
val fileIsPublic = false
ConnectyCube.uploadFile(messageAttachment.path, fileIsPublic, successCallback = { cubeFile ->
// create a message
val chatMessage = ConnectycubeMessage()
chatMessage.saveToHistory = true
// attach a photo
val attachment = ConnectycubeAttachment("photo")
attachment.id = cubeFile.id.toString()
chatMessage.attachments?.add(attachment)
// send a chat message
// ...
}, errorCallback = { ex ->
})
SDK v1 kotlin
val messageAttachment = File("some_image.png")
val fileIsPublic = false
ConnectycubeStorage.uploadFileTask(
messageAttachment,
fileIsPublic
) { progress ->
}.performAsync(object : EntityCallback<ConnectycubeFile> {
override fun onSuccess(storageFile: ConnectycubeFile,
bundle: Bundle?
) {
// create a message
val chatMessage = ConnectycubeChatMessage()
chatMessage.setSaveToHistory(true)
// attach a photo
val attachment = ConnectycubeAttachment("photo")
attachment.id = storageFile.id.toString()
chatMessage.addAttachment(attachment)
// send a chat message
// ...
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
File messageAttachment = new File("some_image.png");
Boolean fileIsPublic = false;
ConnectycubeStorage.uploadFileTask(messageAttachment, fileIsPublic, new ConnectycubeProgressCallback() {
@Override
public void onProgressUpdate(int progressPercentages) {
}
}).performAsync(new EntityCallback<ConnectycubeFile>() {
@Override
public void onSuccess(ConnectycubeFile storageFile, Bundle bundle) {
// create a message
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setSaveToHistory(true);
// attach a photo
ConnectycubeAttachment attachment = new ConnectycubeAttachment("photo");
attachment.setId(file.getId().toString());
chatMessage.addAttachment(attachment);
// send a chat message
// ...
}
@Override
public void onError(ResponseException e) {
}
});
The same flow is supported on the receiver's side. When you receive a message, you need to get the file UID and then download the file from the cloud storage.
SDK v2 kotlin
// ConnectycubeMessageListener
...
override fun onMessage(message: ConnectycubeMessage) {
val url = attachment.url
// process url
}
SDK v1 kotlin
// ChatDialogMessageListener
...
override fun processMessage(dialogId: String,
chatMessage: ConnectycubeChatMessage,
senderId: Int
) {
for (attachment in chatMessage.attachments) {
val fileId = attachment.id
// download a file
ConnectycubeStorage.downloadFile(fileId).performAsync(object : EntityCallback<InputStream> {
override fun onSuccess(inputStream: InputStream,
params: Bundle
) {
// process file
}
override fun onError(errors: ResponseException) {
}
})
}
}
SDK v1 java
// ChatDialogMessageListener
...
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage chatMessage, Integer senderId) {
for (ConnectycubeAttachment attachment : chatMessage.getAttachments()){
String fileId = attachment.getId();
// download a file
ConnectycubeStorage.downloadFile(fileId).performAsync(new EntityCallback<InputStream>(){
@Override
public void onSuccess(InputStream inputStream, Bundle params) {
// process file
}
@Override
public void onError(ResponseException errors) {
}
});
}
}
Contact
A contact profile can be send via chat attachments as well:
SDK v2 kotlin
// create a message
val chatMessage = ConnectycubeMessage(saveToHistory = true)
// build a contact representation
val jc = JsonObject().apply {
add("phone", JsonPrimitive("180032323223"))
add("name", JsonPrimitive("Samuel Johnson"))
}
// attach a contact
val attachment = ConnectycubeAttachment("contact").apply {
data = jc.toString()
}
chatMessage.attachments?.add(attachment)
// send a chat message
// ...
SDK v1 kotlin
// create a message
val chatMessage = ConnectycubeChatMessage().apply {
setSaveToHistory(true)
}
// build a contact representation
val jc = JsonObject().apply {
add("phone", JsonPrimitive("180032323223"))
add("name", JsonPrimitive("Samuel Johnson"))
}
// attach a contact
val attachment = ConnectycubeAttachment("contact").apply {
data = jc.toString()
}
chatMessage.addAttachment(attachment)
// send a chat message
// ...
SDK v1 java
// create a message
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setSaveToHistory(true);
// build a contact representation
JsonObject jc = new JsonObject();
jc.add("phone", new JsonPrimitive("180032323223"));
jc.add("name", new JsonPrimitive("Samuel Johnson"));
// attach a contact
ConnectycubeAttachment attachment = new ConnectycubeAttachment("contact");
attachment.setData(jc.toString());
chatMessage.addAttachment(attachment);
// send a chat message
// ...
SDK v2 kotlin
// ConnectycubeMessageListener
override fun onMessage(message: ConnectycubeMessage) {
for (attachment in message.attachments!!) {
val data = attachment.data
val obj = JsonParser().parse(data).asJsonObject
val phone = obj.getAsJsonPrimitive("phone").asString
val name = obj.getAsJsonPrimitive("name").asString
}
}
SDK v1 kotlin
// ChatDialogMessageListener
...
override fun processMessage(dialogId: String,
chatMessage: ConnectycubeChatMessage,
senderId: Int
) {
for (attachment in chatMessage.attachments) {
val data = attachment.data
val obj = JsonParser().parse(data).asJsonObject
val phone = obj.getAsJsonPrimitive("phone").asString
val name = obj.getAsJsonPrimitive("name").asString
}
}
SDK v1 java
// ChatDialogMessageListener
...
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage chatMessage, Integer senderId) {
for (ConnectycubeAttachment attachment : chatMessage.getAttachments()){
String data = attachment.getData();
JsonObject obj = new JsonParser().parse(data).getAsJsonObject();
String phone = obj.getAsJsonPrimitive("phone").getAsString();
String name = obj.getAsJsonPrimitive("name").getAsString();
}
}
On the receiver's side, when you receive a message, you need to get a contact data from an attachment:
Unread messages count
You can request total unread messages count and unread count for particular conversation:
SDK v2 kotlin
val dialogsIds: MutableList<String> = mutableListOf("546cc3240eda8f2dd7ee2291", "546cc3230eda8f2dd7ee2292")
ConnectyCube.getUnreadMessagesCount(dialogsIds, successCallback = { result ->
Log.i(TAG, "total unread messages: ${result["546cc3240eda8f2dd7ee2291"]}")
Log.i(TAG, "total unread messages: ${result["546cc3230eda8f2dd7ee2292"]}")
}, errorCallback = { error ->
})
SDK v1 kotlin
val dialogsIds: MutableSet<String> = HashSet<String>().apply {
add("546cc3240eda8f2dd7ee2291")
add("546cc3230eda8f2dd7ee2292")
}
val returnBundle = Bundle()
ConnectycubeRestChatService.getTotalUnreadMessagesCount(dialogsIds, returnBundle)
.performAsync(object : EntityCallback<Int> {
override fun onSuccess(total: Int, params: Bundle) {
Log.i(TAG, "total unread messages: $total")
Log.i(TAG, "dialog Unread1: ${params?.getInt("546cc3240eda8f2dd7ee2291")}")
Log.i(TAG, "dialog Unread2: ${params?.getInt("546cc3230eda8f2dd7ee2292")}")
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
Set<String> dialogsIds = new HashSet<String>();
dialogsIds.add("546cc3240eda8f2dd7ee2291");
dialogsIds.add("546cc3230eda8f2dd7ee2292");
ConnectycubeRestChatService.getTotalUnreadMessagesCount(dialogsIds, new Bundle()).performAsync(new EntityCallback<Integer>() {
@Override
public void onSuccess(Integer total, Bundle params) {
Log.i(TAG, "total unread messages: " + total);
Log.i(TAG, "dialog Unread1: " + params.getInt("546cc3240eda8f2dd7ee2291"));
Log.i(TAG, "dialog Unread2: " + params.getInt("546cc3230eda8f2dd7ee2292"));
}
@Override
public void onError(ResponseException e) {
}
});
Global search
Global search feature was developed to simplify search of dialogs, messages and users at the same time.
Similar functionality is used in most popular messengers and you can implement it in your app using Connectycube SDK.
Just use request from snippet below. SearchRequestBuilder
is optional parameter and it can be null
if you don't need
additional configs for search request.
SDK v2 kotlin
val searchText = "searchText" // String or word. Should be longer than 4 symbols. Performs 'or' search.
// For an exact search, you need to wrap the search phrase in quotes.
val searchParams: GlobalSearchParams = GlobalSearchParams() //class-helper to simple config search request
searchParams.dialogIds = dialogsIds // List of dialog ids. Max cam include 10 items. Optional parameter.
searchParams.startDate = startDate // Closest date to now. Uses lte comparison. Optional parameter.
searchParams.endDate = endDate // Shouldn't differ by more than 3 months from the start_date. Uses gte comparison. Optional parameter.
searchParams.limit = 3 // Maximum number of items returned from the server in the search results. Max value - 100. Optional parameter.
ConnectyCube.searchText(dialog.name!!, searchParams.getSearchParams(), successCallback = { searchResult ->
val dialogs = searchResult.dialogs // found dialogs
val messages = searchResult.messages // found messages
val users = searchResult.users // found users
}, errorCallback = { error ->
})
SDK v1 kotlin
val searchText // String or word. Should be longer than 4 symbols. Performs 'or' search.
// For an exact search, you need to wrap the search phrase in quotes.
val searchRequestBuilder = SearchRequestBuilder().apply {
setDialogsIds(dialogsIds) // List of dialog ids. Max cam include 10 items. Optional parameter.
setStartDate(startDate) // Closest date to now. Uses lte comparison. Optional parameter.
setEndDate(endDate) // Shouldn't differ by more than 3 months from the start_date. Uses gte comparison. Optional parameter.
limit = 3 // Maximum number of items returned from the server in the search results. Max value - 100. Optional parameter.
}
ConnectycubeRestChatService.searchByText(searchText, searchRequestBuilder).performAsync(object : EntityCallback<SearchChatEntity> {
override fun onSuccess(result: SearchChatEntity, params: Bundle) {
val dialogs = result.dialogs // found dialogs
val messages = result.messages // found messages
val users = result.users // found users
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
String searchText; // String or word. Should be longer than 4 symbols. Performs 'or' search.
// For an exact search, you need to wrap the search phrase in quotes.
SearchRequestBuilder searchRequestBuilder = new SearchRequestBuilder();
searchRequestBuilder.setDialogsIds(dialogsIds); // List of dialog ids. Max cam include 10 items. Optional parameter.
searchRequestBuilder.setStartDate(startDate); // Closest date to now. Uses lte comparison. Optional parameter.
searchRequestBuilder.setEndDate(endDate); // Shouldn't differ by more than 3 months from the start_date. Uses gte comparison. Optional parameter.
searchRequestBuilder.setLimit(3); // Maximum number of items returned from the server in the search results. Max value - 100. Optional parameter.
ConnectycubeRestChatService.searchByText(searchText, searchRequestBuilder).performAsync(new EntityCallback<SearchChatEntity>() {
@Override
public void onSuccess(SearchChatEntity result, Bundle params) {
ArrayList<ConnectycubeChatDialog> dialogs = result.getDialogs(); // found dialogs
ArrayList<ConnectycubeChatMessage> messages = result.getMessages(); // found messages
ArrayList<ConnectycubeUser> users = result.getUsers(); // found users
}
@Override
public void onError(ResponseException responseException) {
}
});
Chat alerts
When you send a chat message and the recipient/recipients is offline, then automatic push notification will be fired.
In order to receive push notifications you need to subscribe for it. Please refer to Push Notifications guide.
To configure push template which users receive - go to Dashboard Console, Chat Alerts page
Note that currently push notifications are supported on mobile environment only.
Chat notifications settings
Update notifications settings
A user can turn on/off push notifications for offline messages in a dialog. By default push notification are turned ON, so offline user receives push notifications for new messages in a chat.
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val enabled = false //false - to disable push notification, true - to enable
ConnectyCube.updateDialogNotificationsSettings(dialogId, enabled, { result ->
}, { error ->
})
SDK v1 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
val enabled = false //false - to disable push notification, true - to enable
ConnectycubeRestChatService.updateDialogNotificationSending(dialogId, enabled).performAsync(object : EntityCallback<Boolean> {
override fun onSuccess(result: Boolean, params: Bundle) {
//if result == false - push notifications was disabled, otherwise - enabled
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
String dialogId = "5356c64ab35c12bd3b108a41";
boolean enabled = false; //false - to disable push notification, true - to enable
ConnectycubeRestChatService.updateDialogNotificationSending(dialogId, enabled).performAsync(new EntityCallback<Boolean>() {
@Override
public void onSuccess(Boolean result, Bundle params) {
//if result == false - push notifications was disabled, otherwise - enabled
}
@Override
public void onError(ResponseException e) {
}
});
Get notifications settings
Check a status of notifications setting - either it is ON or OFF for a particular chat.
SDK v2 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
ConnectyCube.getDialogNotificationsSettings(dialogId, { enabled ->
}, { error ->
})
SDK v1 kotlin
val dialogId = "5356c64ab35c12bd3b108a41"
ConnectycubeRestChatService.checkIsDialogNotificationEnabled(dialogId).performAsync(object : EntityCallback<Boolean> {
override fun onSuccess(result: Boolean, params: Bundle) {
//result == false - push notifications are disabled,
//result == true - push notifications are enabled
}
override fun onError(e: ResponseException) {
}
})
SDK v1 java
String dialogId = "5356c64ab35c12bd3b108a41";
ConnectycubeRestChatService.checkIsDialogNotificationEnabled(dialogId).performAsync(new EntityCallback<Boolean>() {
@Override
public void onSuccess(Boolean result, Bundle params) {
//result == false - push notifications are disabled,
//result == true - push notifications are enabled
}
@Override
public void onError(ResponseException e) {
}
});
Mark a client as Active/Inactive
When you send a chat message and the recipient/recipients is offline, then automatic push notification will be fired.
Sometimes a client app can be in a background mode, but still online. In this case it's useful to let server know that a user wants to receive push notifications while still is connected to chat.
For this particular case we have 2 handy methods: 'enterInactiveState' and 'enterActiveState':
ConnectycubeChatService.getInstance().enterInactiveState();
ConnectycubeChatService.getInstance().enterActiveState();
The common use case for these APIs is to call 'enterInactiveState' when an app goes to background mode and to call 'enterActiveState' when an app goes to foreground mode.
Contact list
The Contact List API is rather straightforward. User A sends a request to become "friends" with user B. User B accepts the friend request. And now user A and B appear in each other's roster.
Setup Contact List
To access contact list you have to obtain it and set all needed listeners:
SDK v1 kotlin
val rosterListener: RosterListener = object : RosterListener {
override fun entriesDeleted(userIds: Collection<Int?>?) {
}
override fun entriesAdded(userIds: Collection<Int?>?) {
}
override fun entriesUpdated(userIds: Collection<Int?>?) {
}
override fun presenceChanged(presence: ConnectycubePresence?) {
}
}
val subscriptionListener = SubscriptionListener { }
// Do this after success Chat login
val chatRoster = ConnectycubeChatService.getInstance()
.getRoster(ConnectycubeRoster.SubscriptionMode.mutual, subscriptionListener)
chatRoster.addRosterListener(rosterListener)
SDK v1 java
RosterListener rosterListener = new RosterListener() {
@Override
public void entriesDeleted(Collection<Integer> userIds) {
}
@Override
public void entriesAdded(Collection<Integer> userIds) {
}
@Override
public void entriesUpdated(Collection<Integer> userIds) {
}
@Override
public void presenceChanged(ConnectycubePresence presence) {
}
};
SubscriptionListener subscriptionListener = new SubscriptionListener() {
@Override
public void subscriptionRequested(int userId) {
}
};
// Do this after success Chat login
ConnectycubeRoster chatRoster = ConnectycubeChatService.getInstance().getRoster(ConnectycubeRoster.SubscriptionMode.mutual, subscriptionListener);
chatRoster.addRosterListener(rosterListener);
RosterListener
is a listener that is fired any time a contact list is changed or the presence of a user in the contact list is changed (user becomes online/offline)
SubscriptionListener
is a listener that is fired on "subscribe" (add to contact list) request from any user.
Access to the Contact list
Then you can access all contact list items:
SDK v1 kotlin
val entries = chatRoster.entries
SDK v1 java
Collection<ConnectycubeRosterEntry> entries = сhatRoster.getEntries();
A ConnectycubeRosterEntry
describes a user entity in your contact list. To get a user ID of an entry - use getUserId()
method.
Then, you can get a user's status:
SDK v1 kotlin
val userID = 34
val presence: ConnectycubePresence = chatRoster.getPresence(userID)
?: // No user in your roster
return
if (presence.type == ConnectycubePresence.Type.online) {
// User is online
} else {
// User is offline
}
SDK v1 java
int userID = 34;
ConnectycubePresence presence = chatRoster.getPresence(userID);
if (presence == null) {
// No user in your roster
return;
}
if (presence.getType() == ConnectycubePresence.Type.online) {
// User is online
}else{
// User is offline
}
Add user to your contact list
To add user to the contact list use the following snippet:
SDK v1 kotlin
val userID = 34
if (chatRoster.contains(userID)) {
chatRoster.subscribe(userID)
} else {
chatRoster.createEntry(userID, null)
}
SDK v1 java
int userID = 34;
if (chatRoster.contains(userID)) {
try {
chatRoster.subscribe(userID);
} catch (Exception e) {
}
} else {
try {
chatRoster.createEntry(userID, null);
} catch (Exception e) {
}
}
Note
Maximum number of contacts is 300.
Other user will receive the request to be added to the contact list:
SDK v1 kotlin
// SubscriptionListener
override fun subscriptionRequested(userId: Int) {
}
SDK v1 java
// SubscriptionListener
@Override
public void subscriptionRequested(int userId) {
}
Confirm the contact request
To confirm the request use the following method:
SDK v1 kotlin
val userID = 67
chatRoster.confirmSubscription(userID)
SDK v1 java
try {
chatRoster.confirmSubscription(userID);
} catch (Exception e) {
}
Reject the contact request
To reject the request use the following method:
SDK v1 kotlin
val userID = 67
chatRoster.reject(userID)
SDK v1 java
try {
chatRoster.reject(userID);
} catch (Exception e) {
}
Remove user from the contact list
To remove a previously added user from the contact list use the following method:
SDK v1 kotlin
val userID = 67
chatRoster.unsubscribe(userID)
SDK v1 java
int userID = 67;
try {
chatRoster.unsubscribe(userID);
} catch (Exception e) {
}
Contact list updates
So the above RosterListener
listener will give you all the updates regarding contact list changes and users' statuses updates.
Privacy (black) list
Privacy list API allows enabling or disabling communication with other users in a chat. You can create, modify, or delete privacy lists, define a default list.
The user can have multiple privacy lists, but only one can be active.
Create privacy list
A privacy list must have at least one element in order to be created. If no elements specified, then the list with given name will be deleted.
SDK v1 kotlin
val list = ConnectycubePrivacyList().apply {
name = "myList"
}
val items = ArrayList<ConnectycubePrivacyListItem>()
val item1 = ConnectycubePrivacyListItem().apply {
isAllow = false
type = ConnectycubePrivacyListItem.Type.USER_ID
valueForType = 3678.toString()
isMutualBlock = true
}
items.add(item1)
list.items = items
val privacyListsManager = chatService.privacyListsManager
privacyListsManager.createPrivacyList(list)
SDK v1 java
ConnectycubePrivacyList list = new ConnectycubePrivacyList();
list.setName("myList");
ArrayList<ConnectycubePrivacyListItem> items = new ArrayList<ConnectycubePrivacyListItem>();
ConnectycubePrivacyListItem item1 = new ConnectycubePrivacyListItem();
item1.setAllow(false);
item1.setType(ConnectycubePrivacyListItem.Type.USER_ID);
item1.setValueForType(String.valueOf(3678));
item1.setMutualBlock(true);
items.add(item1);
list.setItems(items);
PrivacyListsManager privacyListsManager = chatService.getPrivacyListsManager();
try {
privacyListsManager.createPrivacyList(list);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
The ConnectycubePrivacyListItem
class takes 4 arguments:
- type - use USER_ID to block a user in 1-1 chat or GROUP_USER_ID to block in a group chat.
- valueForType - ID of a user to apply an action
- allow - can be true/false.
- mutualBlock - can be true/false - to block user's message in both directions or not.
In order to be used the privacy list should be not only set, but also activated(set as default).
Activate privacy list
In order to activate rules from a privacy list you should set it as default:
SDK v1 kotlin
privacyListsManager.applyPrivacyList("myList")
SDK v1 java
try {
privacyListsManager.applyPrivacyList("myList");
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
Update privacy list
There are some rules you should follow to update a privacy list:
- Include all of the desired items (not a "delta").
- If you want to update or set new privacy list instead of current one, you should decline current default list first.
SDK v1 kotlin
// Deactivate active list
privacyListsManager.declinePrivacyList()
// Create new list
// ...
// Activate again active list
privacyListsManager.applyPrivacyList("myList")
SDK v1 java
// Deactivate active list
try {
privacyListsManager.declinePrivacyList();
} catch (SmackException|XMPPException.XMPPErrorException e) {
}
// Create new list
// ...
// Activate again active list
try {
privacyListsManager.applyPrivacyList("myList");
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
Retrieve privacy lists
To get a list of all your privacy lists use the following request:
SDK v1 kotlin
val privacyListsManager = ConnectycubeChatService.getInstance().privacyListsManager
val lists = privacyListsManager.privacyLists
SDK v1 java
PrivacyListsManager privacyListsManager = ConnectycubeChatService.getInstance().getPrivacyListsManager()
List<ConnectycubePrivacyList> lists = null;
try {
lists = privacyListsManager.getPrivacyLists();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
Retrieve privacy list with name
To get the privacy list by name you should use the following method:
SDK v1 kotlin
var list = privacyListsManager.getPrivacyList("myList")
SDK v1 java
ConnectycubePrivacyList list = null;
try {
list = privacyListsManager.getPrivacyList("myList");
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
Remove privacy list
Note: Before deleting privacy list you should decline it.
SDK v1 kotlin
privacyListsManager.declinePrivacyList()
privacyListsManager.deletePrivacyList("myList")
SDK v1 java
try {
privacyListsManager.declinePrivacyList();
privacyListsManager.deletePrivacyList("myList");
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
Blocked user attempts to communicate with user
Blocked users will be receiving an error when trying to chat with a user in a 1-1 chat and will be receiving nothing in a group chat:
SDK v1 kotlin
val chatMessage = ConnectycubeChatMessage().apply {
body = "How is going on?"
}
val chatDialog = ...
chatDialog.sendMessage(chatMessage)
...
chatDialog.addMessageListener(object : ChatDialogMessageListener {
override fun processMessage(dialogId: String,
message: ConnectycubeChatMessage,
senderId: Int
) {}
override fun processError(dialogId: String,
exception: ChatException,
message: ConnectycubeChatMessage,
senderId: Int
) {
Log.e(TAG, "processError: " + exception.localizedMessage)
}
})
SDK v1 java
ConnectycubeChatMessage chatMessage = new ConnectycubeChatMessage();
chatMessage.setBody("How is going on?");
ConnectycubeChatDialog chatDialog = ...;
chatDialog.sendMessage(chatMessage);
...
privateDialog.addMessageListener(new ChatDialogMessageListener() {
@Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
@Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
log("processError: " + exception.getLocalizedMessage());
}
});
Log output:
processError: Service not available.
Last activity
There is a way to get an info when a user was active last time, in seconds.
This is a modern approach for messengers apps, e.g. to display this info on a Contacts screen or on a User Profile screen.
SDK v1 kotlin
val userId = 12345
val seconds = ConnectycubeChatService.getInstance().getLastUserActivity(userId)
// seconds - the difference in seconds from current time to last user activity in the chat or 0 if user is online.
SDK v1 java
int userId = 12345;
double seconds = ConnectycubeChatService.getInstance().getLastUserActivity(userId);
// seconds - the difference in seconds from current time to last user activity in the chat or 0 if user is online.
System messages
There is a way to send system messages to other users about some events. System messages work on a separate channel and are not mixed with regular chat messages:
System messages are not stored on a server. It means messages will be delivered only to online users.
SDK v2 kotlin
ConnectyCube.chat.addSystemMessageListener(object : ConnectycubeSystemMessageListener {
override fun onMessage(message: ConnectycubeMessage) {
}
override fun onError(message: ConnectycubeMessage, ex: Throwable) {
}
})
ConnectyCube.chat.sendSystemMessage(message {
recipientId = 58672
properties["param1"] = "value1"
properties["param2"] = "value2"
body = "some text"
})
SDK v1 kotlin
val systemMessagesManager = ConnectycubeChatService.getInstance().systemMessagesManager
val systemMessageListener = object : SystemMessageListener {
override fun processMessage(message: ConnectycubeChatMessage) {
}
override fun processError(exception: ChatException,
message: ConnectycubeChatMessage
) {
}
}
systemMessagesManager.addSystemMessageListener(systemMessageListener)
val systemMessage = ConnectycubeChatMessage().apply {
recipientId = 58672
setProperty("param1", "value1")
setProperty("param2", "value2")
body = "some text"
}
systemMessagesManager.sendSystemMessage(systemMessage)
SDK v1 java
SystemMessagesManager systemMessagesManager = ConnectycubeChatService.getInstance().getSystemMessagesManager();
SystemMessageListener systemMessageListener = new SystemMessageListener() {
@Override
public void processMessage(ConnectycubeChatMessage message) {
}
@Override
public void processError(ChatException exception, ConnectycubeChatMessage message) {
}
};
systemMessagesManager.addSystemMessageListener(systemMessageListener);
ConnectycubeChatMessage systemMessage = new ConnectycubeChatMessage();
systemMessage.setRecipientId(58672);
systemMessage.setProperty("param1", "value1");
systemMessage.setProperty("param2", "value2");
systemMessage.setBody("some text");
try {
systemMessagesManager.sendSystemMessage(systemMessage);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}