Track the online and offline status of users and devices for your app in just a few simple steps with PubNub Presence

Presence Quickstart

Automatic realtime detection of devices and user states to identify who and what is connected.

Presence Quickstart

1

Install PubNub

To start publishing and subscribing, we first need to access PubNub libraries. Include the libraries from CDN or from popular package managers.

View Full JavaScript SDK Documentation
<!-- Include the PubNub Library -->
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.27.3.js"></script>
View Full Android SDK Documentation
// Using Maven
<dependency>
  <groupId>com.pubnub</groupId>
  <artifactId>pubnub-gson</artifactId>
  <version>4.29.2</version>
</dependency>
View Full iOS SDK Documentation
# Create framework using cocoapods
git clone git@github.com:pubnub/objective-c.git

pod install
View Full .NET SDK Documentation
// Using Nuget
https://www.nuget.org/packages/Pubnub/4.5.0.0
/***************
For the 70+ SDKs that PubNub supports go to:
http://www.pubnub.com/docs
****************/

2

Instantiate PubNub

Now you can instantiate a PubNub object using your own publish and subscribe keys.

<!-- Instantiate PubNub -->
<script type="text/javascript">
    var pubnub = new PubNub({
        publishKey: "myPublishKey",
        subscribeKey: "mySubscribeKey",
        ssl: true
    });
</script>
/* Instantiate PubNub */
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setPublishKey("myPublishKey");
pnConfiguration.setSubscribeKey("mySubscribeKey");

PubNub pubnub = new PubNub(pnConfiguration);
/* Instantiate PubNub */
PNConfiguration *configuration = [PNConfiguration configurationWithPublishKey:@"myPublishKey" subscribeKey:@"mySubscribeKey"];
self.client = [PubNub clientWithConfiguration:configuration];
[self.client addListener:self];
/* Instantiate PubNub */
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.PublishKey = "myPublishKey";
pnConfiguration.SubscribeKey = "mySubscribeKey";

Pubnub pubnub = new Pubnub(pnConfiguration);
/***************
For the 70+ SDKs that PubNub supports go to:
http://www.pubnub.com/docs
****************/

3

Enable Presence

Enable Presence on your keys in the Admin Console to use this feature.

4

Subscribe to Presence

Subscribing a channel generates a Join event.These events get broadcast to a special side-channel associated with the channel you are subscribing to. Other Presence events are Join, Leave, Timeout, State-Change and Interval events.

To receive all Presence-related events, we defined a handler for Presence during the subscribe. The state object allows you to include information about the client and/or user with the Presence events.

//Subscribe to the demo_tutorial channel with presence
pubnub.addListener({
    status: function(statusEvent) {
        if (statusEvent.category === "PNConnectedCategory") {
            var newState = {
                name: 'presence-tutorial-user',
                timestamp: new Date()
            };
            pubnub.setState(
                {
                    channels: ["demo_tutorial"],
                    state: newState
                }
            );
        }
    },
    message: function(message) {
        console.log(message);
    },
    presence: function(presenceEvent) {
        console.log(presenceEvent);
    }
})

pubnub.subscribe({
    channels: ["demo_tutorial"],
    withPresence: true
});
/* Subscribe to the demo_tutorial channel with presence and state */
Map<String, Object> state = new HashMap<>();
try {
    state.put("name", "presence-tutorial-user");
    state.put("timestamp", (new Date()).toString());
} catch (JSONException e) {
    e.printStackTrace();
}

pubnub.setPresenceState()
    .channels(Arrays.asList("demo_tutorial"))
    .state(state)
    .uuid(pubnub.getUUID())
    .async(new PNCallback<PNSetStateResult>() {
        @Override
        public void onResponse(PNSetStateResult result, PNStatus status) {

        }
    });
try {
    pubnub.addListener(new SubscribeCallback(){
        @Override
        public void message(PubNub pubnub, PNMessageResult message) {
            JsonNode msg = message.getMessage();
            System.out.println(msg);
        }
    });
    pubnub.subscribe()
        .channels(Arrays.asList("demo_tutorial"))
        .execute();
} catch (PubnubException e) {
    e.printStackTrace();
}

try {
    pubnub.addListener(new SubscribeCallback(){
        @Override
        public void message(PubNub pubnub, PNMessageResult message) {
            JsonNode msg = message.getMessage();
            System.out.println(msg);
        }
    });

    pubnub.subscribe()
        .channels(Arrays.asList("demo_tutorial"))
        .withPresence()
        .execute();

} catch (PubnubException e) {
    e.printStackTrace();
}
NSDictionary *clientState = @{@"demo_tutorial": @{@"name": @"presence-tutorial-user",
                                                                                   @"timestamp": @([[NSDate date] timeIntervalSince1970])}};
[self.client subscribeToChannels:@[@"demo_tutorial"] withPresence:YES clientState:clientState];

- (void)client:(PubNub *)client didReceiveStatus:(PNStatus *)status {

    if (status.operation == PNSubscribeOperation) {

        // Check whether received information about successful subscription or restore.
        if (status.category == PNConnectedCategory || status.category == PNReconnectedCategory) {

            // Status object for those categories can be casted to `PNSubscribeStatus` for use below.
            PNSubscribeStatus *subscribeStatus = (PNSubscribeStatus *)status;
            if (subscribeStatus.category == PNConnectedCategory) {

                // This is expected for a subscribe, this means there is no error or issue whatsoever.
            }
            else {

                /**
                 This usually occurs if subscribe temporarily fails but reconnects. This means there was an error but there is no longer any issue.
                 */
            }
        }
        else if (status.category == PNUnexpectedDisconnectCategory) {

            /**
             This is usually an issue with the internet connection, this is an error, handle appropriately retry will be called automatically.
             */
        }
        // Looks like some kind of issues happened while client tried to subscribe or disconnected from netowrk.
        else {

            PNErrorStatus *errorStatus = (PNErrorStatus *)status;
            if (errorStatus.category == PNAccessDeniedCategory) {

                /**
                 This means that PAM does allow this client to subscribe to this channel and channel group configuration. This is another explicit error.
                 */
            }
            else {

                /**
                 More errors can be directly specified by creating explicit cases for other error categories of `PNStatusCategory` such as: `PNDecryptionErrorCategory`, `PNMalformedFilterExpressionCategory`, `PNMalformedResponseCategory`, `PNTimeoutCategory` or `PNNetworkIssuesCategory`
                 */
            }
        }
    }
    else if (status.operation == PNUnsubscribeOperation) {

        if (status.category == PNDisconnectedCategory) {

            /**
             This is the expected category for an unsubscribe. This means there was no error in unsubscribing from everything.
             */
        }
    }
    else if (status.operation == PNHeartbeatOperation) {

        /**
         Heartbeat operations can in fact have errors, so it is important to check first for an error.
         For more information on how to configure heartbeat notifications through the status PNObjectEventListener callback, consult /docs/ios-objective-c/api-reference-configuration#configuration_basic_usage
         */

        if (!status.isError) {
            /* Heartbeat operation was successful. */
        }
        else {
            /* There was an error with the heartbeat operation, handle here. */
        }
    }
}
/* Subscribe to the demo_tutorial channel with presence and state */
Dictionary<string, object> state = new Dictionary<string, object>();
try {
    state.Add("name", "presence-tutorial-user");
    state.Add("timestamp", (new DateTime()).ToString());
}
catch (Exception e) {
    Console.WriteLine(e.ToString());
}

pubnub.SetPresenceState()
    .Channels(new string[] {
        "demo_tutorial"
    })
    .State(state).Uuid(pnConfiguration.Uuid)
    .Async(new PNSetStateResultExt((result,status)=> {
    }));

try {
    pubnub.AddListener(new SubscribeCallbackExt(
        (pubnubObj, messageResult) => {
            if (messageResult != null) {
                string jsonString = messageResult.Message.ToString();
                Console.WriteLine(jsonString);
            }
        },
        (pubnubObj, presencResult) => {
        },
        (pubnubObj, statusResult) => {
            if (statusResult.Error && statusResult.Category == PNStatusCategory.PNUnknownCategory) {
                Console.WriteLine(statusResult.ErrorData.Information);
            }
        }
  ));


    pubnub.Subscribe<string>()
        .WithPresence()
        .Channels(new string[] {
            "demo_tutorial"
        })
        .Execute();
}
catch (Exception e) {
    Debug.WriteLine(e.ToString());
}
/***************
For the 70+ SDKs that PubNub supports go to:
http://www.pubnub.com/docs
****************/

5

Unsubscribe to Presence

Unsubscribing to a channel generates a Presence Leave event. If a user disconnects from PubNub without unsubscribing (for instance, by closing a browser window), a Timeout event will be generated after 10 minutes.

// Unsubcribe from the channel
pubnub.unsubscribe({
    channels: ['demo_tutorial']
});
/* Unsubcribe from the demo_tutorial and the presence channels */
pubnub.unsubscribe()
    .channels(Arrays.asList("demo_tutorial", "demo_tutorial-pnpres"))
    .execute();
[self.client unsubscribeFromChannels:@[@"demo_tutorial"] withPresence:YES]
/* Unsubcribe from the demo_tutorial and the presence channels */
pubnub.Unsubscribe<string>()
    .Channels(new string[] {
        "demo_tutorial",
        "demo_tutorial-pnpres"
    })
    .Execute();
/***************
For the 70+ SDKs that PubNub supports go to:
http://www.pubnub.com/docs
****************/

6

Detect Users in the Channel

At any time, you can get a list of the current subscribers and the total occupancy count of a channel by calling the hereNow function in your app.

// View the UUID and state objects of those currently subscribed
pubnub.hereNow(
    {
        channels: ['demo_tutorial'],
        includeState: true
    },
    function(status, response) {
        console.log(response);
    }
);
/* View the UUID and state objects of those currently subscribed */
pubnub.hereNow()
    .channels(Arrays.asList("demo_tutorial"))
    .includeState(true)
    .includeUUIDs(true)
    .async(new PNCallback<PNHereNowResult>() {
        @Override
        public void onResponse(PNHereNowResult result, PNStatus status) {

        }
    });
[self.client hereNowForChannel: @"demo_channel"
                withCompletion:^(PNPresenceChannelHereNowResult *result, PNErrorStatus *status) {

    // Check whether request successfully completed or not.
    if (!status) {

        /**
         Handle downloaded presence information using:
             result.data.uuids - dictionary with active subscriber. Each entry will have next
                fields: "uuid" - identifier and "state" if it has been provided.
             result.data.occupancy - total number of active subscribers.
         */
    }
    else {

        /**
         Handle presence audit 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.

         Request can be resent using: [status retry];
         */
    }
}];
/* View the UUID and state objects of those currently subscribed */
pubnub.HereNow()
    .Channels(new string[] {
        "demo_tutorial"
    })
    .IncludeState(true)
    .IncludeUUIDs(true)
    .Async(new PNHereNowResultEx((result, status) => {
    }));
/***************
For the 70+ SDKs that PubNub supports go to:
http://www.pubnub.com/docs
****************/

8

Next Steps

Congratulations! With those few steps, you've successfully used Presence. Checkout Presence Tutorial to see what else can you do with it.

Sign Up for a free PubNub account if you haven't already.

Get coding right away using our 70+ SDKs in your favorite language, or build on top of one of our demo applications.

Try PubNub Today

Try Our APIs
  • 1M Transactions
  • 1GB Data Persistence
  • All major Features