Tracking user presence
Presence lets you track the online and offline status of users and devices in real time and store custom state information. When you have Presence enabled in the Admin Portal, PubNub automatically creates equivalents of all channels that monitor and collect all presence events.
For more information, refer to User Presence.
User ID / UUID
User ID is also referred to as UUID
/uuid
in some APIs and server responses but holds the value of the userId
parameter you set during initialization.
Get user occupancy
Use the hereNow
method to get information about the current state of users in a channel. The call returns a list of unique users currently subscribed to the channel.
- JavaScript
- Java
- Swift
- Objective-C
- Unity
pubnub.hereNow({
channels: ['ch-1'],
includeUUIDs: true,
includeState: true,
}, (status, response) => {
// handle status, response
});
pubnub.hereNow()
.channels(Arrays.asList("ch-1"))
.includeUUIDs(true)
.includeState(true)
.async(result -> {
result.onSuccess(res -> {
Map<String, PNHereNowChannelData> channelsMap = res.getChannels();
for (String channel : channelsMap.keySet()) {
PNHereNowChannelData channelData = channelsMap.get(channel);
System.out.println("Channel: " + channelData.getChannelName());
System.out.println("Occupants: " + channelData.getOccupancy());
for (PNHereNowOccupantData occupant : channelData.getOccupants()) {
System.out.println("\tUserID: " + occupant.getUuid());
System.out.println("\tState: " + occupant.getState());
}
show all 20 linespubnub.hereNow(on: ["ch-1"], also: true) { result in
switch result {
case let .success(response):
print("Successful HereNow Response: \(response)")
case let .failure(error):
print("Failed HereNow Response: \(error.localizedDescription)")
}
}
[self.client hereNowForChannel: @"ch-1" withVerbosity:PNHereNowUUID
completion:^(PNPresenceChannelHereNowResult *result,
PNErrorStatus *status) {
if (!status) {
/**
Handle downloaded presence information using:
result.data.uuids - list of uuids.
result.data.occupancy - total number of active subscribers.
*/
}
else {
}
}];
pubnub.HereNow()
.Channels(new List<string>(){
"ch-1"
})
.IncludeState(true)
.IncludeUUIDs(true)
.Async((result, status) => {
if (status.Error) {
Debug.Log(string.Format("HereNow Error: {0} {1} {2}", status.StatusCode, status.ErrorData, status.Category));
} else {
Debug.Log(string.Format("Channels: {0} {1}", result.TotalChannels, result.TotalOccupancy));
}
Debug.Log(status.Error);
});
User state
Users can set dynamic custom state on one or more channels. This custom state persists on a channel as long as the user stays subscribed to that channel. Some examples of custom states are to add your score, game state, or location in an application if it changes frequently.
Use the setState
method to set dynamic state for a user on channels. A state is an object of key/value pairs with any arbitrary data, as long as the data is of type int
, float
, or string
. When you set or update the state, PubNub fires a state-change
event to other users on the channel.
- JavaScript
- Java
- Swift
- Objective-C
- Unity
pubnub.setState({
state: {
mood: 'grumpy',
},
channels: ['main'],
}, (status, response) => {
// handle state setting response
});
JsonObject state = new JsonObject();
state.addProperty("mood", "grumpy");
pubNub.setPresenceState()
.state(state)
.channels(Arrays.asList("main"))
.async(result -> { /* check result */ });
pubnub.setPresence(
state: ["New": "State"],
on: ["main"]
) { result in
switch result {
case let .success(response):
print("Successful Set State Response: \(response)")
case let .failure(error):
print("Failed Set State Response: \(error.localizedDescription)")
}
}
[self.client setState: @{@"Key": @"Value"} forUUID:self.client.uuid onChannel: @"main"
withCompletion:^(PNClientStateUpdateStatus *status) {
if (!status.isError) {
// Client state successfully modified on specified channel.
}
else {
/**
Handle client state modification error. Check 'category' property
to find out possible reason because of which request did fail.
Review 'errorData' property (which has PNErrorData data type) of status
object to get additional information about issue.
show all 19 linesDictionary<string, object> state = new Dictionary<string, object>();
state.Add("mood", "grumpy");
pubnub.SetPresenceState()
.Channels(new List<string> (){"main"})
.State(state)
.Async((result, status) => {
if(status.Error){
Debug.Log (string.Format("In Example, SetPresenceState Error: {0} {1} {2}", status.StatusCode, status.ErrorData, status.Category));
} else {
Debug.Log (string.Format("DateTime {0}, In Example SetPresenceState, result:", DateTime.UtcNow));
if(result != null){
if(result.StateByChannels!= null){
foreach (KeyValuePair<string, object> key in dict){
Debug.Log(string.Format("Channel:{0}, State:{1}", key.Key, pubnub.JsonLibrary.SerializeToJsonString(key.Value)));
show all 20 linesYou can get state data for any client on a given channel(s) or channel group(s) user the Get State API. This is useful to get the state of other clients based on their User ID.
- JavaScripts
- Java
- Swift
- Objective-C
- Unity
pubnub.getState(
{
uuid: "john-doe",
channels: ["main"],
channelGroups: ["my_channel_group"]
},
function (status, response) {
// handle status, response
}
);
pubnub.getPresenceState()
.channels(Arrays.asList("main"))
.channelGroups(Arrays.asList("my_channel_group"))
.uuid("anotherClientUserID")
.async(result -> { /* check result */ });
pubnub.getPresenceState(
for: "john-doe",
on: ["main"],
and: ["my_channel_group"]
) { result in
switch result {
case let .success(response):
print("Successful Get State Response: \(response)")
case let .failure(error):
print("Failed Get State Response: \(error.localizedDescription)")
}
}
[self.pubnub stateForUUID:@"john-doe" onChannel:@"chats.room1"
withCompletion:^(PNChannelClientStateResult *result, PNErrorStatus *status) {
if (!status) {
}
else {
}
}];
pubnub.GetPresenceState()
.UUID("john-doe")
.Channels(new List<string> (){"main"})
.ChannelGroups(new List<string> (){"my_channel_group"})
.Async((result, status) => {
if(status.Error){
Debug.Log (string.Format(" GetPresenceState Error: {0} {1} {2}", status.StatusCode, status.ErrorData, status.Category));
} else {
Debug.Log (string.Format("DateTime {0}, In Example GetPresenceState, result:", DateTime.UtcNow));
if(result != null){
if(result.StateByChannels!= null){
foreach (KeyValuePair<string, object> key in dict){
Debug.Log(string.Format("Channel:{0}, State:{1}", key.Key, pubnub.JsonLibrary.SerializeToJsonString(key.Value)));
}
show all 19 linesFor more details on working with user state, refer to Setting Custom Presence State.
Presence events
PubNub triggers presence events as users come online or go offline from the application. Clients can receive these events directly, or you can use webhooks on a server to keep a user's online/offline status up to date. Use these events to keep track of users coming and going and the total occupancy of the channel.
Events | Description |
---|---|
join | Fires when a user subscribes to a channel. |
leave | Fires when a user unsubscribes from a channel. |
timeout | Fires when a connection to a channel is lost and the subscriber hasn't been seen in 320 seconds (just over 5 minutes). |
state-change | Fires anytime the user's state is changed using the state API (function signature varies by SDK). |
interval | Fires to provide an occupancy count. The default setting for the Presence Interval property is 10 seconds, which is configurable on your Admin Portal's Presence add-on panel. |
Join event:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "join",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user1",
"timestamp": 1511946669
}
Leave event:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "leave",
"timetoken": "15119446002445794",
"occupancy": 1,
"uuid": "user1",
"timestamp": 1511944600
}
Timeout event:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "timeout",
"timetoken": "15119519897494311",
"occupancy": 3,
"uuid": "user1",
"timestamp": 1511951989
}
User state change event:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "state-change",
"state": {
"mood": "grumpy"
},
"timetoken": "15119477895378127",
"occupancy": 5,
"uuid": "user1",
"timestamp": 1511947789
}
Interval event:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "interval",
"timetoken": "15119477895378127",
"occupancy": 2,
"timestamp": 1511947739
}