Use case: real-time chat¶
Overview¶
With a combination of the GetSocial Activity Feed and Notifications API, you can implement real-time user-to-user or group chat.
Just like news feeds, chats keep users engaged in your app and give them one more reason to get back.
Implementation guide¶
This guide shows you how to create chat-like Activity Feeds for each pair (or group) of users who want to chat and send notifications about new messages with Notifications API.
0. Prerequisite¶
-
Integrate GetSocial SDK. Check the detailed guide on Android, iOS or Unity.
-
Setup push notifications. Check the detailed setup guide on Android, iOS or Unity.
1. Design UI¶
UI defines the look and feel for your chat view, making it visually distinct from Activity Feed. Core elements include:
- Different message styling for sender and recipient.
- List of messages with an input field.
2. Generate unique identifier for chat¶
Create a unique Activity Feed for each pair (or group) of users who want to chat. For consistency, you have to ensure that they get same chat id (feed id, in fact).
```java tab=”Android(Java)”
String generateChatId(String… userIds) {
// Sort to get the same chat id for same participants
Arrays.sort(userIds);
1 2 3 4 5 6 |
|
}
kotlin tab=”Android(Kotlin)”
fun generateChatId(userIds: Array
// Sort to get the same chat id for same participants
return “chat_${userIds.sorted().joinToString(separator = “_”)}”
}
```
```objc tab=”iOS(Objective-C)”
- (NSString *)chatIdForUsers: (NSArray *) userIds
{
NSArray *sortedIds = [userIds sortedArrayUsingSelector:@selector(compare:)];
NSString *chatId = [sortedIds componentsJoinedByString:@”_”];
1 |
|
}
swift tab=”iOS(Swift)”
func generateChatId(_ userIds : [String]) -> String {
// Sort to get the same chat id for same participants
let chatId = userIds.sorted().joined(separator: “”)
return “chat(chatId)”
}
```
```csharp tab=”Unity”
private string GenerateChatId(params string[] userIds)
{
// Sort to get the same chat id for same participants
Array.Sort(userIds);
1 |
|
}
```
Feed Naming
Use prefix’s like “chat_” to distinguish chat feeds from regular ones on Developer’s Dashboard.
Feed ID Restrictions
Feed name could contain only alphanumeric symbols: letters [a-z]
, numbers [0-9]
, -
, _
, .
; and should not be longer than 64 symbols.
3. Load messages¶
To load message use GetSocial.getActivities
. Messages are sorted historically (newest posts first), so be sure to reverse the order of messages before showing them to the user.
java tab="Android(Java)"
GetSocial.getActivities(ActivitiesQuery.postsForFeed(chatId).withLimit(50), new Callback<List<ActivityPost>>() {
@Override
public void onSuccess(List<ActivityPost> messages) {
// Reversing list to have resulting posts in right order
Collections.reverse(messages);
// Show messages on the UI
showMessages(messages);
}
@Override
public void onFailure(GetSocialException e) {
Log.e("GetSocial", "Activities loading failed, error: " + e.getMessage());
}
});
```kotlin tab=”Android(Kotlin)”
GetSocial.getActivities(ActivitiesQuery.postsForFeed(chatId), object : Callback>{
override fun onSuccess(activityPostList: List
// Reversing list to have resulting posts in right order
val messages = activityPostList.reversed()
1 2 3 4 5 6 7 |
|
})
```objc tab="iOS(Objective-C)"
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForFeed:chatId];
[query setLimit:50];
[GetSocial activitiesWithQuery:query
success:^(NSArray<GetSocialActivityPost *> *messages) {
// Reversing list to have resulting posts in right order
messages = [[messages reverseObjectEnumerator] allObjects];
// Show messages on the UI
[self showMessages:messages];
}
failure:^(NSError *error) {
NSLog(@"Failed to get messages, error: %@", error);
}
];
```swift tab=”iOS(Swift)”
let query = GetSocialActivitiesQuery.posts(forFeed: chatId)
query.setLimit(50)
GetSocial.activities(with: query,
success: { (messages: [GetSocialActivityPost]) in
// Reversing list to have resulting posts in right order
let messages = messages.reversed()
1 2 3 4 5 |
|
csharp tab=”Unity”
var chatId = GenerateChatId(new[] {GetSocial.User.Id, Receiver.Id});
var query = ActivitiesQuery.PostsForFeed(chatId).WithLimit(50);
GetSocial.GetActivities(query, messages =>
{
// Reversing list to have resulting posts in right order
messages.Reverse();
// Show messages on the UI
ShowMessages(messages);
},
error =>
{
Debug.Log(“Failed to get messages, error: ” + error);
});
```
4. Post message¶
To send a message, it’s enough to specify its text. Sender info is attached to it by SDK. Using ActivityPostContent
you can also share media content like images, gifs and videos.
```java tab=”Android(Java)”
ActivityPostContent messageContent = ActivityPostContent
.createBuilderWithText(“Hi, it’s nice to have a separate chat!”).build();
GetSocial.postActivityToFeed(chatId, messageContent, new Callback
@Override
public void onSuccess(ActivityPost chatMessage) {
Log.i(“GetSocial”, “You message was successfully posted!”);
}
1 2 3 4 |
|
});
kotlin tab=”Android(Kotlin)”
val messageContent = ActivityPostContent
.createBuilderWithText(“Hi, it’s nice to have a separate chat!”).build()
GetSocial.postActivityToFeed(chatId, messageContent, object: Callback
override fun onSuccess(chatMessage: ActivityPost) {
print(“Successfully posted a message.”)
}
override fun onFailure(exception: GetSocialException) {
print(“Failed to post a message, error: ${exception.message}”)
}
})
```
```objc tab=”iOS(Objective-C)”
GetSocialActivityPostContent *messageContent = [GetSocialActivityPostContent new];
postContent.text = @”Hi, it’s nice to have a separate chat!”;
[GetSocial postActivity:messageContent
toFeed:chatId
success:^(GetSocialActivityPost *post) {
NSLog(@”Successfully posted a message.”);
} failure:^(NSError *error) {
NSLog(@”Failed to post a message, error: %@”, error);
}];
```swift tab="iOS(Swift)"
let messageContent = GetSocialActivityPostContent()
messageContent.text = "Hi, it's nice to have a separate chat!"
GetSocial.postActivity(messageContent, toFeed: "chatId", success: { (post : GetSocialActivityPost) in
print("Successfully posted a message.")
}) { (error : Error) in
print("Failed to post a message, error: \(error.localizedDescription)")
}
```csharp tab=”Unity”
var feedId = GenerateChatId(new[] {GetSocial.User.Id, Receiver.Id});
var messageContentBuilder = ActivityPostContent.CreateBuilder();
messageContentBuilder.WithText(“Hi, it’s nice to have a separate chat!”);
GetSocial.PostActivityToFeed(feedId, messageContentBuilder.Build(), post => {
Debug.Log(“Successfully posted a message.”);
}, error => {
Debug.Log(Failed to post a message, error: ” + error);
});
### 5. Notify recipient about the message
When you send a message in a chat, a notification for the recipient should be generated. Activity Feeds do not provide this functionality, so you have to send notifications manually using Notifications API.
```java tab="Android(Java)"
private void sendChatMessageNotification(String messageContent, String recipientId) {
// Create custom Notification action, so when we receive we can distinguish that this is chat notification
Action action = Action.builder("open_chat_message")
.addActionData("open_messages_for_id", GetSocial.User.getId())
.build();
NotificationContent notificationContent = NotificationContent
.notificationWithText(messageContent)
.withTitle(GetSocial.User.getDisplayName())
.withAction(action);
GetSocial.User.sendNotification(Collections.singletonList(recipientId), notificationContent, new Callback<NotificationsSummary>() {
@Override
public void onSuccess(NotificationsSummary result) {
Log.i("GetSocial", "Chat notification sent");
}
@Override
public void onFailure(GetSocialException exception) {
Log.e("GetSocial", "Failed to send chat notification, error: " + exception.getMessage());
}
});
}
```kotlin tab=”Android(Kotlin)”
private fun sendChatMessageNotification(messageContent: String, recipientId: String) {
// Create custom Notification action, so when we receive we can distinguish that this is chat notification
val action = Action.builder(“open_chat_message”)
.addActionData(“open_messages_for_id”, GetSocial.User.getId())
.build()
val notificationContent = NotificationContent
.notificationWithText(messageContent)
.withTitle(GetSocial.User.getDisplayName())
.withAction(action)
GetSocial.User.sendNotification(listOf(recepientId), notificationContent
, object : Callback
override fun onSuccess(summary: NotificationsSummary) {
print(“Chat notification sent”)
}
1 2 3 4 |
|
}
objc tab=”iOS(Objective-C)”
- (void)sendNotificationForMessage:(NSString *)message recipient: (NSString *) recipientId
{
// Sender user id to generate chat id on the recipient side
NSDictionary *messageMetadata = @{@”sender_id” : GetSocialUser.userId};
// Create custom Notification action, so when we receive we can distinguish that this is chat notification
GetSocialActionBuilder *action = [[GetSocialActionBuilder alloc] initWithType:@”open_chat_message”];
[action addActionData:messageMetadata];
GetSocialNotificationContent *notificationContent = [GetSocialNotificationContent withText:message];
[notificationContent setTitle:GetSocialUser.displayName];
[notificationContent setAction:[action build]];
[GetSocialUser sendNotification:@[ recipientId ]
withContent:notificationContent
success:^(GetSocialNotificationsSummary *summary) {
NSLog(@”Chat notification sent”);
}
failure:^(NSError *error) {
NSLog(@”Failed to send chat notifications, error: %@”, error);
}];
}
```
```swift tab=”iOS(Swift)”
func sendNotification(message: String, recipientId : String) {
// Sender user id to generate chat id on the recipient side
let messageMetadata = [“sender_id” : GetSocialUser.userId()]
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
}
csharp tab=”Unity”
void SendNotification(string message, string recipientId)
{
var builder = GetSocialAction.CreateBuilder(“open_chat_message”)
.AddActionData(“sender_id”, GetSocial.User.Id);
var notificationContent = NotificationContent.NotificationWithText(message)
.WithTitle(GetSocial.User.DisplayName)
.WithAction(builder.Build());
var recepients = new List
GetSocial.User.SendNotification(recepients, notificationContent, summary =>
{
Debug.Log(“Chat notification sent”);
}, error =>
{
Debug.Log(“Failed to send chat notifications, error: ” + error);
});
}
```
6. Handle incoming notification¶
To enable behavior, like opening your chat view, it’s essential to set up listener, where you can receive notifications.
```java tab=”Android(Java)”
GetSocial.setNotificationListener(new NotificationListener() {
public boolean onNotificationReceived(Notification notification, boolean wasClicked) {
if (“open_chat_message”.equals(notification.getAction().getType())) {
String senderId = action.getData().get(“sender_id”);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
});
kotlin tab=”Android(Kotlin)”
GetSocial.setNotificationListener { notification, wasClicked ->
if (“open_chat_message”.equals(notification.action.type)) {
val senderId = notification.action.data[“sender_id”]!!
if (wasClicked) {
// Show chat UI for Activity Feed with id chatId if notification was clicked by user
showChatWithUser(senderId)
} else {
// you can check here if chat is open now with the user and append a message to the chat
if (hasChatOpenWithUser(senderId)) {
appendMessageToChat(notification.getText())
}
}
return@setNotificationListener true
}
false
}
```
```objc tab=”iOS(Objective-C)”
[GetSocial setNotificationHandler:^BOOL(GetSocialNotification *notification, BOOL wasClicked) {
if ([@”open_chat_message” isEqualToString:notification.notificationAction.type]) {
NSString *senderId = notification.notificationAction.data[@”sender_id”];
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
}];
swift tab=”iOS(Swift)”
GetSocial.setNotificationHandler { (notification: GetSocialNotification, wasClicked : Bool) -> Bool in
if (“open_chat_message” == notification.notificationAction.type.rawValue) {
let senderId = notification.notificationAction.data[GetSocialActionDataKey(rawValue: “sender_id”)]!
if (wasClicked) {
// Show chat UI for Activity Feed with id chatId if notification was clicked by user
self.showChatWithUser(senderId);
} else {
// you can check here if chat is open now with user and append message to the chat
if (self.hasChatOpenWithUser(senderId)) {
self.appendMessageToChat(notification.text);
}
}
return true
}
return false
}
```
```csharp tab=”Unity”
GetSocial.SetNotificationListener((notification, wasClicked) =>
{
if (notification.NotificationAction.Type.Equals(“open_chat_message”))
{
var senderId = notification.NotificationAction.Data[“sender_id”];
if (wasClicked)
{
// Show chat UI for Activity Feed with id chatId if notification was clicked by user
ShowChatWithUser(senderId);
} else
{
// you can check here if chat is open now with user and append message to the chat
if (HasChatOpenWithUser(senderId))
{
AppendMessageToChat(notification.Text);
}
}
1 2 |
|
});
```
6. Managing chats on the Dashboard¶
All user to user chats are visible on the GetSocial Dashboard in the Activity Feed section. You can manage chats, just like any Activity Feed.
The only downside, Activity Feed names contain GetSocial User Ids which are not readable.
Try it out¶
Download DevFest Ukraine conference application to check out the user-to-user chat demo.
Also, you can find implementation in our Android, iOS or Unity demo applications on GitHub.
Next steps¶
- Check what else you can build with Activity Feed API.
- Learn more about Activity Feeds API.
- Learn more about Notifications API.