Skip to content

Implementing Chat with Activity Feed API

Currently, we don’t support chats as a separate feature, but you can replicate functionality with existing GetSocial APIs.

This guide will show 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.

You can find implementation example in our demo application on GitHub.

Design UI

UI will define the look and feel for your chat view, making it visually distinct from Activity Feed. Core elements will include:

  • Different message styling for sender and recipient.

  • List of messages with an input field.

Generate unique identifier for chat

We will create a uniques Activity Feed for each pair (or group) of users who want to chat. For consistency, you have to ensure that they get identical chat id (feed id, in fact).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
String generateChatId(String ... userIds) {
    // Sort to get the same chat id for same participants 
    Arrays.sort(userIds);

    StringBuilder builder = new StringBuilder("chat");
    for(String id : userIds) {
        builder.append("_").append(id);
    }

    return builder.toString();
}
1
2
3
4
5
6
7
- (NSString *)chatIdForUsers: (NSArray *) userIds
{
    NSArray *sortedIds = [userIds sortedArrayUsingSelector:@selector(compare:)];
    NSString *chatId = [sortedIds componentsJoinedByString:@"_"];

    return [@"chat_" stringByAppendingString:chatId];
}
1
2
3
4
5
6
func generateChatId(_ userIds : [String]) -> String {
    // Sort to get the same chat id for same participants
    let chatId = userIds.sorted().joined(separator: "_")

    return "chat_\(chatId)"
}
1
2
3
4
5
6
7
private string GenerateChatId(string[] userIds)
{
    // Sort to get the same chat id for same participants
    Array.Sort(userIds);

    return "chat_" + string.Join("_", userIds);
}

Feed naming

Use prefix’s like “chat_” to distinguish chat feeds from regular ones on Developer’s Dashboard.

Feed name restrictions

Feed name could contain only alphanumeric symbols: letters [a-z], numbers [0-9], -, _, .; and should be not longer than 64 symbols.

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
GetSocial.getActivities(ActivitiesQuery.postsForFeed(chatId), 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
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Activities loading failed, error: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForFeed:chatId];

[GetSocial activitiesWithQuery:query
    success:^(NSArray<GetSocialActivityPost *> *messages) {
        // Reversing list to have resulting posts in right order
        NSArray *reversedMessages = [[messages reverseObjectEnumerator] allObjects];        

        // Show messages on the UI
    }
    failure:^(NSError *error) {
        NSLog(@"Failed to get messages, error: %@", error);
    }
];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let query = GetSocialActivitiesQuery.posts(forFeed: chatId)

GetSocial.activities(with: query, 
    success: { (posts: [GetSocialActivityPost]) in
        // Reversing list to have resulting posts in right order
        let reversedMessages = posts.reversed()

        // Show messages on the UI
    }) { (error: Error) in
        print("Failed to get messages, error: \(error.localizedDescription)")
    }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var chatId = GenerateChatId(new[] {GetSocial.User.Id, Receiver.Id});
var query = ActivitiesQuery.PostsForFeed(chatId);

GetSocial.GetActivities(query, list =>
    {
        _messages.AddAll(list);
        // Reversing list to have resulting posts in right order
        _messages.Reverse();

        // Show messages on the UI
    }, 
    error =>
    {
        Debug.Log("Failed to get messages, error: " + error);
    });

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 video’s.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ActivityPostContent messageContent = ActivityPostContent
    .createBuilderWithText("Hi, it's nice to have a separate chat!").build();

GetSocial.postActivityToFeed(chatId, messageContent, new Callback<ActivityPost>() {
    @Override
    public void onSuccess(ActivityPost chatMessage) {
        Log.i("GetSocial", "You message was successfully posted!");
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Posting failed, error: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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);
                }];
1
2
3
4
5
6
7
8
let messageContent = GetSocialActivityPostContent.init()
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)")
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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);
});

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 we have to send notifications manually using Notifications API.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void sendChatMessageNotification(String messageContent, String recipientId) {
    Map<String, String> messageMetadata = new HashMap<>();
    messageMetadata.put("open_messages_for_id", GetSocial.User.getId()); // Sender user id to generate chat id on the recipient side

    // Create custom Notification action, so when we receive we can distinguish that this is chat notification
    Action action = Action.builder("open_chat_message")
            .addActionData(messageMetadata)
            .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());
        }
    });
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (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);
        }];
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
func sendNotification(message: String, recepientId : String) {
    // Sender user id to generate chat id on the recipient side
    let messageMetadata = ["sender_id" : GetSocialUser.userId()]

    // Create custom Notification action, so when we receive we can distinguish that this is chat notification
    let action = GetSocialActionBuilder.init(type: GetSocialActionType(rawValue: "open_chat_message"))
    action.addActionData(messageMetadata)

    let noficiationContent = GetSocialNotificationContent.withText(message)
    noficiationContent.setTitle(GetSocialUser.displayName()!)
    noficiationContent.setAction(action.build())

    GetSocialUser.sendNotification([recepientId], with: noficiationContent, success: { (summary : GetSocialNotificationsSummary) in
        print("Chat notification sent")
    }) { (error : Error) in
        print("Failed to send chat notifications, error: \(error.localizedDescription)")
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void SendNotification(string message, string recepientId)
{
    var messageData = new Dictionary<string, string> {{"sender_id", GetSocial.User.Id}};

    var builder = GetSocialAction.CreateBuilder("open_chat_message");
    builder.AddActionData(messageData);

    var notificationContent = NotificationContent.NotificationWithText(message);
    notificationContent.WithTitle(GetSocial.User.DisplayName);
    notificationContent.WithAction(builder.Build());

    var recepients = new List<string> {recepientId};
    GetSocial.User.SendNotification(recepients, notificationContent, summary => { 
        Debug.Log("Chat notification sent");
    }, error => {
        Debug.Log("Failed to send chat notifications, error: " + error);
    });
}

Handle incoming notification

To enable behaviour, like opening your chat view, it’s essential to set up listener, where you can receive notifications.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
GetSocial.setNotificationListener(new NotificationListener() {
    public boolean onNotificationReceived(Notification notification, boolean wasClicked) {
        if ("open_chat_message".equals(notification.getAction().getType())) {
            // User clicked on the chat related push notification, let's open the chat

            String senderId = action.getData().get("open_messages_for_id");
            String chatId = generateChatId(GetSocial.User.getId(), senderId);

            // Show chat UI for Activity Feed with id chatId

            return true;
        }

        return false;
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[GetSocial setNotificationHandler:^BOOL(GetSocialNotification *notification, BOOL wasClicked) {
    if ([@"open_chat_message" isEqualToString:notification.notificationAction.type]) {
        // User clicked on the chat related push notification, let's open the chat

        NSString *senderId = notification.notificationAction.data[@"open_messages_for_id"];
        NSString *chatId = [self chatIdForUsers:@[GetSocialUser.userId, senderId]];

        // Show chat UI for Activity Feed with id chatId

        return YES;
    }

    return NO;
}];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
GetSocial.setNotificationHandler { (notification: GetSocialNotification, wasClicked : Bool) -> Bool in
    if ("open_chat_message" == notification.notificationAction.type.rawValue) {
        // User clicked on the chat related push notification, let's open the chat

        let senderId = notification.notificationAction.data[GetSocialActionDataKey(rawValue: "open_messages_for_id")]!
        let chatId = self.generateChatId([GetSocialUser.userId(), senderId])

        // Show chat UI for Activity Feed with id chatId

        return true
    }
    return false
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
GetSocial.SetNotificationListener((notification, wasClicked) =>
{
    if (notification.NotificationAction.Type.Equals("open_chat_message"))
    {
        var senderId = notification.NotificationAction.Data["open_messages_for_id"];
        var chatId = GenerateChatId(new[] {GetSocial.User.Id, Receiver.Id});

        // Show chat UI for Activity Feed with id chatId

        return true;
    }
});

Managing chats on the Dashboard

All user to user chats will be visible on the GetSocial Dashboard in the Activity Feed section. You can manage chats, just like any Activity Feed.

The only big donwnside, Activity Feed names will contain GetSocial User Ids which are not readable.

Chats on Dashboard

Putting it all together

You can find implementation in our Android, iOS or Unity demo applications on GitHub.

Next steps

Give us your feedback! Was this article helpful?

😀 🙁