Skip to content

Load Activity Feed content

Activity Feed consists of posts and announcements. Each post and announcement have a list of comments and likes.

In the following guide, we’ll show how to query all sorts of Activity Feed content.

Save time with prebuilt Activity Feed UI

Activity Feed UI Features
Let your users post, comment and like on your Activity Feed with one line of code with prebuilt UI. Check Activity Feed UI guide for more details.

Prerequisite

Load posts

To get a list of posts on the Activity Feed, you have to create a query and call API to get the results:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ActivitiesQuery query = ActivitiesQuery.postsForGlobalFeed();

GetSocial.getActivities(query, new Callback<List<ActivityPost>>() {
    @Override
    public void onSuccess(List<ActivityPost> activityPosts) {
        Log.i("GetSocial", "Successfully retrieved activities list");
        // Show activityPosts on the UI
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Failed to get activities, error: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
val query = ActivitiesQuery.postsForGlobalFeed()

GetSocial.getActivities(query, object: Callback<List<ActivityPost>>{
    override fun onSuccess(activityPostList: List<ActivityPost>) {
        println("Successfully retrieved activities list")
        // Show activityPosts on the UI
    }

    override fun onFailure(exception: GetSocialException) {
        println("Failed to get activities, error: ${exception.message}")
    }
})
1
2
3
4
5
6
7
8
9
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];

[GetSocial activitiesWithQuery:query
                    success:^(NSArray<GetSocialActivityPost *> *activityPosts) {
                        NSLog(@"Successfully retrieved activity posts.");
                        // Show activityPosts on the UI
                    } failure:^(NSError *error) {
        NSLog(@"Failed to get activity posts, error: %@", error);
    }];
1
2
3
4
5
6
7
8
let query = GetSocialActivitiesQuery.postsForGlobalFeed()

GetSocial.activities(with: query, success: { activityPosts in
    print("Successfully retrieved activity posts.")
    // Show activityPosts on the UI
}, failure: { error in
    print("Failed to get activity posts, error: \(error)")
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ActivitiesQuery query = ActivitiesQuery.PostsForGlobalFeed();

GetSocial.GetActivities(query,
    activityPosts => {
        Debug.Log("Successfully retrieved activity posts list");
        // Show activityPosts on the UI
    },
    error => {
        Debug.LogWarning("Failed to get activity posts, error: " + error.Message);
    });

Create a query

To create query you have to specify for which feed id you want to load posts.

1
2
3
4
5
String feedId = "sample-feed-id";
ActivitiesQuery query = ActivitiesQuery.postsForFeed(feedId);

// Convenience constructor to create a query for the default global feed  
ActivitiesQuery query = ActivitiesQuery.postsForGlobalFeed();
1
2
3
4
5
val feedId = "sample-feed-id"
val query = ActivitiesQuery.postsForFeed(feedId)

// Convenience constructor to create a query for the default global feed  
val query = ActivitiesQuery.postsForGlobalFeed()
1
2
3
4
5
NSString *feedId = @"sample-feed-id";
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForFeed:feedId];

// Convenience constructor to create a query for the default global feed  
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];
1
2
3
4
5
let feedId = "sample-feed-id"
let query = GetSocialActivitiesQuery.postsForFeed(feedId)

// Convenience constructor to create a query for the default global feed
let query = GetSocialActivitiesQuery.postsForGlobalFeed()
1
2
3
4
5
string feedId = "sample-feed-id";
ActivitiesQuery query = ActivitiesQuery.PostsForFeed(feedId);

// Convenience constructor to create a query for the default global feed  
ActivitiesQuery query = ActivitiesQuery.PostsForGlobalFeed();

Pagination

Query class supports pagination. By default, it retrieves first posts with limit=10.

You can provide the number of activity posts to load and specify if you want to load chronologically older or newer posts relative to provided activity post id.

1
2
3
4
5
6
ActivityPost oldestActivity = ... ; // Reference to the oldest loaded activity post

ActivitiesQuery query = ActivitiesQuery
        .postsForGlobalFeed()
        .withFilter(ActivitiesQuery.Filter.OLDER, oldestActivity.getId())
        .withLimit(15);
1
2
3
4
5
6
val oldestActivity = ...  // Reference to the oldest loaded activity post

val query = ActivitiesQuery
    .postsForGlobalFeed()
    .withFilter(ActivitiesQuery.Filter.OLDER, oldestActivity.id)
    .withLimit(15)
1
2
3
4
5
GetSocialActivityPost *oldestActivity = ... ; // Reference to the oldest loaded activity post

GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];
[query setLimit:15];
[query setFilter:ActivitiesBefore activityId:oldestActivity.activityId];
1
2
3
4
5
let oldestActivity = ... // Reference to the oldest loaded activity post

let query = GetSocialActivitiesQuery.postsForGlobalFeed()
query.setLimit(15)
query.setFilter(GetSocialActivitiesFilter.ActivitiesBefore, activityId: oldestActivity.activityId)
1
2
3
4
5
6
ActivityPost oldestActivity = ... ; // Reference to the oldest loaded activity post

ActivitiesQuery query = ActivitiesQuery
    .PostsForGlobalFeed()
    .WithFilter(ActivitiesQuery.Filter.Older, oldestActivity.Id)
    .WithLimit(15);

Posts by user

Query class allows you to query activities posted by the provided user. By default, it retrieves all activities.

For example, to get activities posted by current user:

1
2
3
4
String userId = GetSocial.User.getId();
ActivitiesQuery query = ActivitiesQuery
        .postsForGlobalFeed()
        .filterByUser(userId);
1
2
3
4
val userId = GetSocial.User.getId()
val query = ActivitiesQuery
        .postsForGlobalFeed()
        .filterByUser(userId)
1
2
3
GetSocialId userId = [GetSocialUser userId];
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];
[query setFilterByUser:userId];
1
2
3
let userId: GetSocialId = GetSocialUser.userId()
let query = GetSocialActivitiesQuery.postsForGlobalFeed()
query.setFilterByUser(userId)
1
2
3
4
string userId = GetSocial.User.Id;
ActivitiesQuery query = ActivitiesQuery
        .PostsForGlobalFeed()
        .FilterByUser(userId);

Posts by friends

You can ask to give you activities in feed, that were posted by you and your friends:

1
2
3
ActivitiesQuery query = ActivitiesQuery
        .postsForGlobalFeed()
        .friendsFeed(true);
1
2
3
val query = ActivitiesQuery
        .postsForGlobalFeed()
        .friendsFeed(true)
1
2
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];
[query setIsFriendsFeed:YES];
1
2
let query = GetSocialActivitiesQuery.postsForGlobalFeed()
query.setIsFriendsFeed(true)
1
2
3
ActivitiesQuery query = ActivitiesQuery
        .PostsForGlobalFeed()
        .FriendsFeed(true);

Posts with tags

You can filter all activities by tags, so you will have only activities that contain at least one tag from the provided list:

1
2
3
ActivitiesQuery query = ActivitiesQuery
        .postsForGlobalFeed()
        .withTags("cat", "dog", "animal");
1
2
3
val query = ActivitiesQuery
        .postsForGlobalFeed()
        .withTags("cat", "dog", "animal")
1
2
GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery postsForGlobalFeed];
[query setTags:@[@"cat", @"dog", @"animal"]];
1
2
let query = GetSocialActivitiesQuery.postsForGlobalFeed()
query.setTags(["cat", "dog", "animal"])
1
2
3
ActivitiesQuery query = ActivitiesQuery
        .PostsForGlobalFeed()
        .WithTags("cat", "dog", "animal");

Load announcements

To get a list of announcements that are active now:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
String feedId = "sample-feed-id";

// To get announcements for the global feed  
// use convenience method GetSocial.getGlobalFeedAnnouncements(callback)
GetSocial.getAnnouncements(feedId, new Callback<List<ActivityPost>>() {
    @Override
    public void onSuccess(List<ActivityPost> activityPosts) {
        Log.i("GetSocial", "Successfully loaded announcements list");
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Load failed: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
val feedId = "sample-feed-id"
// To get announcements for the global feed
// use convenience method GetSocial.getGlobalFeedAnnouncements(callback)
GetSocial.getAnnouncements(feedId, object: Callback<List<ActivityPost>> {
    override fun onSuccess(activityPosts: List<ActivityPost>) {
        println("Successfully loaded announcements list")
    }

    override fun onFailure(exception: GetSocialException) {
        println("Load failed, error: ${exception.message}")
    }

})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
NSString *feedId = @"sample-feed-id";

// To get announcements for the global feed  
// use convenience method [GetSocial announcementsForGlobalFeedWithSuccess: ... failure: ... ]
[GetSocial announcementsForFeed:feedId
                        success:^(NSArray<GetSocialActivityPost *> *announcements) {
                            NSLog(@"Successfully retrieved a list of announcements");
                        } failure:^(NSError *error) {
            NSLog(@"Failed to get a list of announcements, error: %@", error);
        }];
1
2
3
4
5
6
7
8
9
let feedId = "sample-feed-id"

// To get announcements for the global feed  
// use convenience method GetSocial.announcementsForGlobalFeed(success: ... , failure: ... )
GetSocial.announcements(forFeed: feedId, success: { announcements in
    print("Successfully retrieved a list of announcements")
}, failure: { error in
    print("Failed to get a list of announcements, error: \(error)")
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
string feedId = "sample-feed-id";

// To get announcements for the global feed  
// use convenience method GetSocial.GetGlobalFeedAnnouncements(callback)
GetSocial.GetAnnouncements(feedId,
    announcements => {
        Debug.Log("Succesfully retrieved a list of announcements!");
    },
    error => {
        Debug.LogWarning("Failed to get a list of announcements, error: " + error.Message);
    });

Load comments

For each activity post or announcement you can check comments count and get the list of comments for the activity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
ActivityPost activityPost = ...; // Instance of activity post, announcement or comment

int count = activityPost.getCommentsCount();

ActivitiesQuery query = ActivitiesQuery.commentsToPost(activityPost.getId());
GetSocial.getActivities(query, new Callback<List<ActivityPost>>() {
    @Override
    public void onSuccess(List<ActivityPost> activityPosts) {
        Log.i("GetSocial", "Successfully retrieved comments list!");
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Retrieving failed: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
val activityPost : ActivityPost = ... // Instance of activity post, announcement or comment

val count = activityPost.commentsCount

val query = ActivitiesQuery.commentsToPost(activityPost.id)
GetSocial.getActivities(query, object: Callback<List<ActivityPost>>{
    override fun onSuccess(activityPosts: List<ActivityPost>?) {
        println("Successfully retrieved comments list!")
    }

    override fun onFailure(exception: GetSocialException?) {
        println("Retrieving failed, error: ${exception.message}")
    }

})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
GetSocialActivityPost *activityPost = ...; // Instance of activity post, announcement or comment

NSInteger count = [activityPost commentsCount];

GetSocialActivitiesQuery *query = [GetSocialActivitiesQuery commentsToPost:[activityPost activityId]];
[GetSocial activitiesWithQuery:query success:^(NSArray<GetSocialActivityPost *> *comments) {
    NSLog(@"Successfully retrieved comments!");
} failure:^(NSError *error) {
    NSLog(@"Failed to get comments, error: %@", error);
}];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
GetSocialActivityPost activityPost = ... // Instance of activity post, announcement or comment

let count: Int = activityPost.commentsCount()

let query = GetSocialActivitiesQuery.comments(toPost: activityPost.activityId())
GetSocial.activities(with: query, success: { comments in
    print("Successfully retrieved comments!")
}, failure: { error in
    print("Failed to get comments, error: \(error)")
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ActivityPost activityPost = ...; // Instance of activity post, announcement or comment

int count = activityPost.CommentsCount;

ActivitiesQuery query = ActivitiesQuery.CommentsToPost (activityPost.Id);
GetSocial.GetActivities (query,
    posts => {
        Debug.Log ("Succesfully retrieved comments list!");
    },
    error => {
        Debug.LogWarning ("Failed to get comments, error: " + error.Message);
    });

Load likes

For each activity post, announcement and comment you can check the likes count, was it liked by the current user and get the list of users who liked the activity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
ActivityPost activityPost = ...; // Instance of activity post, announcement or comment

int count = activityPost.getLikesCount();
boolean isLikedByMe = activityPost.isLikedByMe();

GetSocial.getActivityLikers(activityPost.getId(), offset, limit, new Callback<List<PublicUser>>() {
    @Override
    public void onSuccess(List<PublicUser> publicUsers) {
        Log.i("GetSocial", "Successfully retrieved list of activity likers");
        // showListOfUsers(publicUsers);
    }

    @Override
    public void onFailure(GetSocialException e) {
        Log.e("GetSocial", "Retrieving failed: " + e.getMessage());
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
val activityPost : ActivityPost = ... // Instance of activity post, announcement or comment

val count = activityPost.likesCount
val isLikedByMe = activityPost.isLikedByMe

GetSocial.getActivityLikers(activityPost.id, offset, limit, object: Callback<List<PublicUser>> {
    override fun onSuccess(publicUsers: List<PublicUser>) {
        println("Successfully retrieved list of activity likers")
        // showListOfUsers(publicUsers);
    }

    override fun onFailure(exception: GetSocialException) {
        println("Retrieving failed, error: ${exception.message}")
    }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
GetSocialActivityPost *activityPost = ...; // Instance of activity post, announcement or comment

NSInteger count = [activityPost likesCount];
BOOL isLikedByMe = [activityPost isLikedByMe];

[GetSocial activityLikers:[activityPost activityId]
                    offset:offset
                    limit:limit
                    success:^(NSArray<GetSocialPublicUser *> *users) {
                        NSLog(@"Successfully retrieved a list of users who liked an activity.");
                        // [self showUsersList:users];
                    } failure:^(NSError *error) {
                        NSLog(@"Failed to retrieve likers list, error: %@", error);
                    }];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
GetSocialActivityPost activityPost = ... // Instance of activity post, announcement or comment

let count: Int = activityPost.likesCount()
let isLikedByMe: Bool = activityPost.isLikedByMe()

GetSocial.activityLikers(activityPost.activityId(), offset: offset, limit: limit, success: { users in
    print("Successfully retrieved a list of users who liked an activity.")
    // self.showUsersList(users)
}, failure: { error in
    print("Failed to retrieve likers list, error: \(error)")
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ActivityPost activityPost = ...; // Instance of activity post, announcement or comment

int count = activityPost.LikesCount;
boolean isLikedByMe = activityPost.IsLikedByMe;


GetSocial.GetActivityLikers (activityPost.Id, offset, limit,
    users => {
        Debug.Log("Successfully retrieved a list of activity likers!");
        // showUsersList(users);
    },
    error => {
        Debug.LogWarning("Failed to get a list of activity likers, error: " + error.Message);
    });

Where offset and limit is pagination parameters, for example, to get first 50 users, who liked a post, use offset=0 and limit=50, to get next page - offset=50, limit=50 etc.

Working with activity post

The section below explains how you can display Activity Post Content after loading it from GetSocial API.

Post Author and Creation Date

Each post, announcement, and comment contains a set of metadata that you can use on your UI:

1
2
3
4
ActivityPost post = ...; // Instance of activity post, announcement or comment

PostAuthor author = post.getAuthor();
long createdAt = post.getCreatedAt(); // UNIX-timestamp of creation date in seconds
1
2
3
4
val post : ActivityPost = ... // Instance of activity post, announcement or comment

val author = post.author
val createdAt = post.createdAt // UNIX-timestamp of creation date in seconds
1
2
3
4
GetSocialActivityPost *post = ...; // Instance of activity post, announcement or comment

GetSocialPostAuthor *author = [post author];
NSUInteger createdAt = [post createdAt]; // UNIX-timestamp of creation date in seconds
1
2
3
4
GetSocialActivityPost post = ... // Instance of activity post, announcement or comment

let author: GetSocialPostAuthor = post.author()
let createdAt: Int = post.createdAt() // UNIX-timestamp of creation date in seconds
1
2
3
4
ActivityPost post = ...; // Instance of activity post, announcement or comment

PostAuthor author = post.Author;
DateTime createdAt = post.CreatedAt;

Text

Text content can contain text itself, mentions, tags, and URLs.

User ids from mentions in the text are replaced by API to user display names. If you posted text like Hello @0128309218! where @0128309218 is user id, API returns text like Hello Ben!.

Optionally you can make URLs on your UI clickable.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
TextView contentText = ...; // Get instance of text view
ActivityPost post = ...; // Instance of activity post, announcement or comment

if (post.hasText()) {
    String textContent = post.getText();
    contentText.setText(textContent);

    // Don't forget to make text views accessible
    contentText.setContentDescription(textContent);

    // Optionally, make links clickable if post was made from Dashboard 
    if (post.getAuthor().isVerified()) { 
        Linkify.addLinks(contentText, Linkify.WEB_URLS);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
val contentText: TextView = ... // Get instance of text view
val post : ActivityPost = ... // Instance of activity post, announcement or comment
if (post.hasText()) {
    val textContent = post.text
    contentText.text = textContent

    // Don't forget to make text views accessible
    contentText.contentDescription(textContent)

    // Optionally, make links clickable if post was made from Dashboard 
    if (post.author.isVerified) {
        Linkify.addLinks(contentText, Linkify.WEB_URLS)
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
UITextView *contentText = ...; // Get the instance of text view
GetSocialActivityPost *post = ...; // Instance of activity post, announcement or comment

if (post.text) {
    contentText.text = post.text;

    // Don't forget to make text views accessible
    contentText.accessibilityValue = post.text;

    // Optionally, make links clickable if post was made from Dashboard
    if (post.author.verified) {
        contentText.dataDetectorTypes = UIDataDetectorTypeLink;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var contentText: UITextView? = ... // Get the instance of text view
var post: GetSocialActivityPost? = ... // Instance of activity post, announcement or comment

guard let text = post.text else {
    return
}
contentText.text = post.text

// Don't forget to make text views accessible
contentText.accessibilityValue = post.text

// Optionally, make links clickable if post was made from Dashboard
if post.author.verified {
    contentText.dataDetectorTypes = .link
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Text contentText = ... ; // 
ActivityPost post = ... ; // Instance of activity post, announcement or comment

if (post.HasText)
{
    contentText.text = post.Text;

    // Optionally, make links clickable if post was made from Dashboard
    if (post.Author.IsVerified)
    {
        // Unity does not provide any solution for clickable links in text, so you probably want to implement some custom view or look for a ready solution on Github or Asset Store
    }
}

Mentions

To highlight mentions in the text and make them clickable:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Spannable spannable = new SpannableString(post.getText());

for (Mention mention : post.getMentions()) {
    final int startIndex = mention.getStartIndex();
    final int endIndex = mention.getEndIndex();

    spannable.setSpan(new BackgroundColorSpan(Color.YELLOW), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannable.setSpan(new ForegroundColorSpan(Color.BLUE), startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    spannable.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View view) {
            // Handle click
        }
    }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

contentText.setText(spannable);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
val spannable = SpannableString(post.text)
post.mentions.forEach { mention ->
    val startIndex = mention.startIndex
    val endIndex = mention.endIndex

    spannable.setSpan(BackgroundColorSpan(Color.YELLOW), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    spannable.setSpan(ForegroundColorSpan(Color.BLUE), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

    spannable.setSpan({ widget: View ->
        // handle click
    }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}

contentText.text = spannable
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:post.text];
for (GetSocialMention *mention in post.mentions) {
    NSRange effectiveRange = NSMakeRange(mention.startIndex, mention.endIndex - mention.startIndex);
    [mutableAttributedString addAttributes:@{
        NSBackgroundColorAttributeName : [UIColor yellowColor],
        NSForegroundColorAttributeName : [UIColor blueColor],
    } range:effectiveRange];
}

contentText.attributedText = mutableAttributedString;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var mutableAttributedString = NSMutableAttributedString(string: post.text!)
for mention in post.mentions {
    var effectiveRange = NSRange(location: Int(mention.startIndex), length: Int(mention.endIndex - mention.startIndex))
    mutableAttributedString.addAttributes([
        NSAttributedString.Key.backgroundColor: UIColor.yellow,
        NSAttributedString.Key.foregroundColor: UIColor.blue
        ], range: effectiveRange)
}

contentText.attributedText = mutableAttributedString
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Do not forget to enable `Rich text` for your Text element in Unity Editor or in code
contentText.supportRichText = true;

var richText = post.Text;
var totalOffset = 0;
post.Mentions.ForEach(mention =>
{
    richText = richText.Insert(mention.StartIndex + totalOffset, "<color=blue>");
    totalOffset += "<color=blue>".Length;
    richText = richText.Insert(mention.EndIndex + totalOffset, "</color>");
    totalOffset += "</color>".Length;
    // Unity does not provide the default way to change the background of part of the text, you probably want to implement some custom view or look for a ready solution on Github or Asset Store
});

contentText.text = richText;

Tags

To highlight tags in the text and make them clickable, you may use code like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Spannable spannable = new SpannableString(post.getText());
final Matcher matcher = Pattern.compile("(#[\\p{L}\\d_]*\\p{L}[\\p{L}\\d_]*)").matcher(spannable);

while (matcher.find()) {
    final int startIndex = matcher.start();
    final int endIndex = matcher.end();

    spannable.setSpan(new BackgroundColorSpan(Color.YELLOW), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannable.setSpan(new ForegroundColorSpan(Color.BLUE), startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    spannable.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View view) {
            // Handle click
        }
    }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
val spannable = SpannableString(post.text)
val matcher = Pattern.compile("(#[\\p{L}\\d_]*\\p{L}[\\p{L}\\d_]*)").matcher(spannable)
while (matcher.find()) {
    val startIndex = mention.startIndex
    val endIndex = mention.endIndex

    spannable.setSpan(BackgroundColorSpan(Color.YELLOW), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    spannable.setSpan(ForegroundColorSpan(Color.BLUE), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

    spannable.setSpan({ widget: View ->
        // handle click
    }, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:post.text];
NSString *pattern = @"(#[\\p{L}\\d_]*\\p{L}[\\p{L}\\d_]*)";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
[regex enumerateMatchesInString:post.text
                        options:0
                        range:NSMakeRange(0, post.text.length)
                   usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags __unused flags, BOOL __unused *stop) {
                            NSRange effectiveRange = result.range;
                            [mutableAttributedString addAttributes:@{
                                NSBackgroundColorAttributeName : [UIColor yellowColor],
                                NSForegroundColorAttributeName : [UIColor blueColor],
                            } range:effectiveRange];
                    }];

self.contentText.attributedText = mutableAttributedString;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
let mutableAttributedString = NSMutableAttributedString(string: post.text!)
let pattern = "(#[\\p{L}\\d_]*\\p{L}[\\p{L}\\d_]*)"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
regex.enumerateMatches(in: post.text!, options: [], range: NSRange(location: 0, length: post.text!.count), using: { result, flags, stop in
    var effectiveRange: NSRange? = result?.range
    if let effectiveRange = effectiveRange {
        mutableAttributedString.addAttributes([
            NSAttributedString.Key.backgroundColor: UIColor.yellow,
            NSAttributedString.Key.foregroundColor: UIColor.blue
            ], range: effectiveRange)
    }
})

contentText.attributedText = mutableAttributedString
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Do not forget to enable `Rich text` for your Text element in Unity Editor or in code
contentText.supportRichText = true;

var pattern = "(#[\\p{L}\\d_]*\\p{L}[\\p{L}\\d_]*)";
var matches = Regex.Matches(post.Text, pattern);
var totalOffset = 0;
var richText = post.Text;
foreach (Match match in matches)
{
    var groups = match.Groups[0];
    Console.WriteLine("'{0}' repeated at positions {1}-{2}",  
                        groups.Value, groups.Index, groups.Length);
    richText = richText.Insert(groups.Index + totalOffset, "<color=blue>");
    totalOffset += "<color=blue>".Length;
    richText = richText.Insert(groups.Index + groups.Length + totalOffset, "</color>");
    totalOffset += "</color>".Length;
}

contentText.text = richText;

Media attachments

Activity Post can contain images and videos. GIFs are converted to videos for optimization. All videos are encoded in MP4.
Check Media Attachments guide for more details.

1
2
3
4
5
6
7
8
if (post.hasVideo()) {
    // When you post video, GetSocial generates video preview automatically
    // setVideoPreview(post.getImageUrl());

    // setVideo(post.getVideoUrl());
} else if (post.hasImage()) {
    // setImage(post.getImageUrl());
}
1
2
3
4
5
6
7
8
if (post.hasVideo()) {
    // When you post video, GetSocial generates video preview automatically
    // setVideoPreview(post.imageUrl)

    // setVideo(post.videoUrl)
} else if (post.hasImage()) {
    // setImage(post.imageUrl
}
1
2
3
4
5
6
7
8
if (post.videoUrl.length > 0) {
    // When you post video, GetSocial generates video preview automatically
    // [self setVideoPreview:post.imageUrl];

    // [self setVideo:post.videoUrl];
} else if (post.imageUrl.length > 0) {
    // [self setImage:post.imageUrl];
}
1
2
3
4
5
6
7
8
if post.videoUrl != nil && !post.videoUrl!.isEmpty {
    // When you post video, GetSocial generates video preview automatically
    // self.setVideoPreview(post.imageUrl)

    // self.setVideo(post.videoUrl)
} else if post.imageUrl != nil && !post.imageUrl!.isEmpty {
    // self.setImage(post.imageUrl)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
if (!string.IsNullOrEmpty(post.VideoUrl))
{
    // When you post video, GetSocial generates video preview automatically
    // SetVideoPreview(post.ImageUrl);

    // SetVideo(post.VideoUrl);
} else if (post.HasImage)
{
    // SetImage(post.ImageUrl);
}

Action buttons

The code below shows how to display the button and implement a combination of custom action handling with the one provided by GetSocial.

Check GetSocial Actions guide for Android, iOS or Unity for more information.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Button button = ... ; // An instance of button for the activity post

if (post.hasButton()) {
    button.setText(post.getButtonTitle());

    // Don't forget to make view accessible
    button.setContentDescription(post.getButtonTitle());

    button.setOnClickListener((View view) -> {
        Action action = post.getAction();
        if ("my-custom-type".equals(action.getType())) {
            // Do the custom action handling
        } else {
            GetSocial.processAction(action); // Let GetSocial handle the action
        }
    });
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
val button : Button = ... // An instance of button for the activity post

if (post.hasButton()) {
    button.text = post.buttonTitle

    // Don't forget to make view accessible
    button.setContentDescription(post.buttonTitle)

    button.setOnClickListener { view ->
        val action = post.action
        if ("my-custom-type".equals(action.getType())) {
            // Do the custom action handling
        } else {
            GetSocial.processAction(action) // Let GetSocial handle the action
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
UIButton *actionButton = ... ; // An instance of button for the activity post

if (post.buttonTitle.length > 0) {
    [actionButton setTitle:post.buttonTitle forState:UIControlStateNormal];

    // Don't forget to make view accessible
    actionButton.accessibilityValue = post.buttonTitle;

    actionButton.tag = [self.posts indexOfObject:post];
    UITapGestureRecognizer *actionButtonTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didClickActionButton:)];
    actionButtonTap.numberOfTapsRequired = 1;
    [actionButton addGestureRecognizer:actionButtonTap];
}

- (void)didClickActionButton:(UITapGestureRecognizer *)sender {
    GetSocialActivityPost *post = self.posts[sender.view.tag];
    if ([post.action.type isEqualToString:@"my-custom-type"]) {
        // Do the custom action handling
    } else {
        [GetSocial processAction:post.action];
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var actionButton: UIButton = ... // An instance of button for the activity post
if let buttonTitle = post.buttonTitle {
    actionButton.setTitle(buttonTitle, for: .normal)

    // Don't forget to make view accessible
    actionButton.accessibilityValue = buttonTitle

    actionButton.tag = posts.index(of: post)
    let actionButtonTap = UITapGestureRecognizer(target: self, action: #selector(self.didClickActionButton(_:)))
    actionButtonTap.numberOfTapsRequired = 1
    actionButton.addGestureRecognizer(actionButtonTap)
}

@objc func didClickActionButton(_ sender: UITapGestureRecognizer?) {
    guard let index = sender?.view?.tag else {
        return
    }
    let post: GetSocialActivityPost? = posts[index]
    if post.action.type == "my-custom-type" {
        // Do the custom action handling
    } else {
        GetSocial.processAction(post.action)
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
if (post.HasButton)
{
    button.GetComponentInChildren<Text>().text = post.ButtonTitle;
    button.onClick.AddListener (() => {
        var action = post.Action;
        if ("my-custom-type".Equals(action.Type))
        {
            // Do the custom action handling
        } else
        {
            GetSocial.ProcessAction(action); // Let GetSocial handle the action
        }
    });
}

Next steps

Give us your feedback! Was this article helpful?

😀 🙁