# Presence and Timeline Events

### Setting user presence

User presence is a vital ingredient of any solid messaging platform. Mitter.io is no exception. The SDK gives you multiple ways to update your user’s presence without the hassle.

#### What is a presence?

Presence, as the name suggests, is the current availability of a user. It is usually a single word which tells whether the user is currently available to chat or is not available at the moment.

You can [learn more about presence](https://docs.mitter.io/platform-reference-1/users#user-presence) and how Mitter.io handles them in the reference section.

#### Exploring the bundled presence types

The Mitter Android SDK ships with a couple of default presence types which you can use to get started:

* Online
* Away
* Sleeping
* Missing
* Offline

Each of these presence types has a `timeToLive` field which indicates the time in seconds up to which a presence is valid. After the time has elapsed, the user presence automatically shifts to the next presence in line (if any).

#### Updating your user’s presence

The SDK allows you to update the current user’s presence in two ways:

* Update the presence manually
* Tell the SDK to keep updating the presence automatically

Regardless of which approach you choose, you need a `Presence` object, to begin with. Therefore, let’s build one:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val presence = PresenceBuilder()
    .startWith(StandardUserPresenceTypes.online(15))
    .then(StandardUserPresenceTypes.away(30))
    .then(StandardUserPresenceTypes.sleeping(60))
    .then(StandardUserPresenceTypes.offline())
    .build()
```

{% endtab %}

{% tab title="Java" %}

```java
Presence presence = new PresenceBuilder()
    .startWith(StandardUserPresenceTypes.INSTANCE.online(15))
    .then(StandardUserPresenceTypes.INSTANCE.away(30))
    .then(StandardUserPresenceTypes.INSTANCE.sleeping(60))
    .then(StandardUserPresenceTypes.INSTANCE.offline(0))
    .build();
```

{% endtab %}
{% endtabs %}

Here, we’re using the handy `PresenceBuilder` to build a cascading presence in a fluent manner. In a nutshell, the user’s presence begins with `Online` then shifts to `Away` after **15 seconds** and so on.

Now that you have the `Presence` object, you can choose either the manual approach or the automatic one for updating. It’s recommended that you use the *automatic approach* as it’s less management work for you.

**Update presence automatically**

To start updating the current user’s presence automatically, all you need to do is call the `startAutoUpdateCurrentUserPresence()` method on the `Users` object:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
users.startAutoUpdateCurrentUserPresence(presence)
```

{% endtab %}

{% tab title="Java" %}

```java
users.startAutoUpdateCurrentUserPresence(presence, 5);
```

{% endtab %}
{% endtabs %}

What’s happening behind the scenes is that the SDK periodically polls on your behalf to update the current user’s presence as `Online`. Once the user exits your app, it stops polling and as a result, the presence starts expiring to the next status as discussed earlier.

> Note: Here, the second argument value is the polling interval (in secs). Therefore, this example sets polling every 5 seconds.

**Update presence manually**

If you prefer not to use the automatic approach, the SDK also allows you to update the current user’s presence in a single shot.

To update the current user’s presence you need to call the `setCurrentUserPresence()` method on the `Users` object. Something like this:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
users.setCurrentUserPresence(
    presence,
    object : Mitter.OnValueUpdatedCallback {
        override fun onSuccess() {
            Log.d("Mitter", "Presence updated!")
        }

        override fun onError(error: ApiError) {
            Log.d("Mitter", "User Presence - ApiError: $error")
        }
    }
)
```

{% endtab %}

{% tab title="Java" %}

```java
users.setCurrentUserPresence(
    presence,
    new Mitter.OnValueUpdatedCallback() {
        @Override
        public void onSuccess() {
            Log.d("Mitter", "Presence updated!");
        }

        @Override
        public void onError(ApiError apiError) {
            Log.d("Mitter", "User Presence - ApiError: " + apiError);
        }
    }
);
```

{% endtab %}
{% endtabs %}

> **Note**: This is a one-shot update call. If you don’t make this call periodically, the current user’s presence will shift to the next expiring presence after the `timeToLive` has elapsed, even if your app is open.

#### Fetching another user’s presence

Just as you to seamlessly set the current user’s presence, you can easily fetch any user’s presence by calling the `getUserPresence()` method on the `Users` object.

Just do the following:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
users.getUserPresence(
    userId = "debd7e00-1c3e-463c-92d1-dbb0e9e0e4ba",
    onValueAvailableCallback = object : Mitter.OnValueAvailableCallback<Presence> {
        override fun onValueAvailable(value: Presence) {
            Log.d("Mitter", "Presence: ${value.type}")
        }

        override fun onError(apiError: ApiError) {
            Log.d("Mitter", "User Presence - ApiError: $error")
        }
    }
)
```

{% endtab %}

{% tab title="Java" %}

```java
users.getUserPresence(
    "debd7e00-1c3e-463c-92d1-dbb0e9e0e4ba",
    new Mitter.OnValueAvailableCallback<Presence>() {
        @Override
        public void onValueAvailable(Presence presence) {
            Log.d("Mitter", "Presence: " + presence.getType());
        }

        @Override
        public void onError(ApiError apiError) {
            Log.d("Mitter", "User Presence - ApiError: " + apiError);
        }
    }
);
```

{% endtab %}
{% endtabs %}

Unlike setting a presence, the SDK doesn’t currently provide an automatic presence fetching mechanism. This means that you’ll have to poll this call with a short time interval let’s say every **5 seconds**, to continuously stay in sync with the other user’s presence.

A good place for doing this would be your chat screen. You can call this method every **5** or **10 seconds** on the chat screen for every other participant in the chat *except* the current user.

That’s all you need to know about handling presence for users. Now, we’ll move on to another interesting topic which is dealing with timeline events.

### Adding timeline events

In the previous sections, we’ve talked a lot about timeline events. You’ve also noticed that you need to add a `SentTime` timeline event to every message you sent.

You must be wondering, how are the useful exactly and if there are other types of timeline events that you can use. Good news, there are some other timeline events that you can use out the box while always having the ability to spin up a custom event of your own.

#### What are timeline events?

Think of timeline events as categorised timestamp for all activities by a user. Learn more [here](https://docs.mitter.io/platform-reference-1/messages#timeline-events).

#### Exploring the standard timeline events

Although you can create any custom type of timeline events, Mitter.io provides a set of event types out of the box. Currently, there are **4 standard** event types shipped by Mitter.io:

* `mitter.mtet.SentTime` - The time at which the message was sent
* `mitter.mtet.ReceivedTime` - The time at which the message was received by the server
* `mitter.mtet.DeliveredTime` - The time at which the message was delivered to the user
* `mitter.mtet.ReadTime` - The time at which the message was read by the user

While you can any of these standard events from the SDK, the SDK provides convenience methods for the `mitter.mtet.DeliveredTime` and `mitter.mtet.ReadTime` events where you don’t have to set these types explicitly. You’ll see how.

#### Adding a standard timeline event to a message

Taking an use case of adding a read receipt to a message, this can easily be done by calling the `addReadTimelineEvent()` method on the `Messaging` object. Here’s a quick demo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
messaging.addReadTimelineEvent(
    channelId = "b8bcb84d-8ad2-4f8a-816e-92772b2b8055",
    messageIds = listOf(
        "89a3de83-769e-4b62-8fee-b50b197c09b4",
        "8e5ea0fe-82e1-4b12-b6ca-5f33d965c0fa"
    )
)
```

{% endtab %}

{% tab title="Java" %}

```java
messaging.addReadTimelineEvent(
    "b8bcb84d-8ad2-4f8a-816e-92772b2b8055",
    Arrays.asList(
        "89a3de83-769e-4b62-8fee-b50b197c09b4",
        "8e5ea0fe-82e1-4b12-b6ca-5f33d965c0fa"
    ),
    null
);
```

{% endtab %}
{% endtabs %}

In this example, we’re adding a read timeline event to **2 messages** at once without explicitly setting the timeline event type and putting in any timestamp. The SDK does the job for you.

You can, also, attach an optional callback to this method as the last parameter `onValueUpdatedCallback`, if you want to be notified after the operation has succeeded.

#### Adding a customised timeline event to a message

When you grow out the standard use cases, you might want to use the `addTimelineEvent()` method to add a timeline event to your messages. This method accepts a `TimelineEvent` object which you need to construct on your own, fully customised to your needs.

**Preparing the TimelineEvent object**

Before sending out any event, you need to construct a `TimelineEvent` object with some required parameters, as follows:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val timelineEvent = TimelineEvent(
    type = "com.acme.events.GiftCardOpened",
    eventTimeMs = System.currentTimeMillis(),
    subject = User().setUserId("3764e344-5a53-4c02-8bfa-2b3bc11e7c0e")
)
```

{% endtab %}

{% tab title="Java" %}

```java
TimelineEvent timelineEvent = new TimelineEvent(
    UUID.randomUUID().toString(),
    "",
    "com.acme.events.GiftCardOpened",
    System.currentTimeMillis(),
    new User().setUserId("3764e344-5a53-4c02-8bfa-2b3bc11e7c0e"),
    null
);
```

{% endtab %}
{% endtabs %}

Here, the `type` is the type of the event that you’re sending, `eventTimeMs` is the timestamp you want to associate with the event and the `subject` is the user with whom this event should be associated.

For example, if you’re sending a read time type of event, the `subject` would the receiving user who has read the message.

**Sending the event**

Now that you have the event prepared with your necessary customisations, it’s time to actually send it out for Mitter.io to deliver it to the concerned user(s).

You can do the same by calling the `addTimelineEvent()` method and supplying the `TimelineEvent` object that you created in the previous step. This is how the code looks:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
messaging.addTimelineEvent(
    channelId = "b8bcb84d-8ad2-4f8a-816e-92772b2b8055",
    messageIds = listOf(
        "89a3de83-769e-4b62-8fee-b50b197c09b4",
        "8e5ea0fe-82e1-4b12-b6ca-5f33d965c0fa"
    ),
    timelineEvent = timelineEvent
)
```

{% endtab %}

{% tab title="Java" %}

```java
messaging.addTimelineEvent(
    "b8bcb84d-8ad2-4f8a-816e-92772b2b8055",
    Arrays.asList(
        "89a3de83-769e-4b62-8fee-b50b197c09b4",
        "8e5ea0fe-82e1-4b12-b6ca-5f33d965c0fa"
    ),
    timelineEvent,
    null
);
```

{% endtab %}
{% endtabs %}

As you can notice, it’s almost the same as the `addReadTimelineEvent()` method with the exception that it accepts a `TimelineEvent` object without assuming anything on it’s own.

This is how you can have full control over what events you want to send out.

### Wrap up

This section has dealt with some advanced properties of Mitter.io and how you can leverage them to work the way you want.

In the next section, you’ll learn how to update your user’s profile and adding certain locators that’ll help you find any user in your application.
