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

Presence Getting Started Guide

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

Presence Getting Started Guide

1

Install PubNub

To start publishing and subscribing, we first need to access our PubNub libraries. Include the code hosted on our CDN just before closing your HTML </body> tag.

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

Remember to enable Presence on your keys in the Admin Console to use this feature!


/* View the Full Documentation. */
/* Instantiate PubNub */
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setPublishKey("Your Publish Key Here");
pnConfiguration.setSubscribeKey("Your Subscribe Key Here");

PubNub pubnub = new PubNub(pnConfiguration);


/* View the Full Documentation. */
/* Instantiate PubNub */
PNConfiguration *configuration = [PNConfiguration configurationWithPublishKey:@"Your publish key" 

subscribeKey:@"Your subscribe key"];
self.client = [PubNub clientWithConfiguration:configuration];
[self.client addListener:self];


<!-- View the Full Documentation. -->
<!-- Include the PubNub Library -->
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.[version number].js"></script>

<!-- Instantiate PubNub -->
<script type="text/javascript">

    var pubnubDemo = new PubNub({
        publishKey: 'Your Publish Key Here',
        subscribeKey: 'Your Subscribe Key Here'
    });

</script>


//  View the Full Documentation.
// Instantiate PubNub
Pubnub pubnub = new Pubnub(
   publishKey:"Your Publish Key Here", 
   subscribeKey:"Your Subscribe Key Here"
);

/***************
For all other languages,
check out the 70+ SDKs that PubNub supports
on our documentation page:
/docs
****************/

2

Subscribe with Presence Events

When Presence is enabled, subscribing to a channel generates a Join event. Likewise unsubscribing generates a Leave event. These events get broadcast to a special side-channel associated with the channel you are subscribing to.

To receive all Presence-related events, we defined a handler for Presence during the subscribe. The PubNub SDKs automatically subscribe to the associated side-channel for Presence Join, Leave, Timeout, State-Change and Interval events and we can log those to the console as well.

The state object allows you to include information about the client and/or user with the Presence events. That way, displaying associated information (like a user name and a timestamp) becomes much simpler since it is included with all broadcasted Presence events.


/* 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 http://www.pubnub.com/docs/ios-objective-c/api-reference#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
pubnubDemo.addListener({
    status: function(statusEvent){
        if (statusEvent.category === "PNConnectedCategory") {
            var newState = {
                name: 'presence-tutorial-user',
                timestamp: new Date()
            };
            pubnubDemo.setState(
                { 
                    channels: ["demo_tutorial"],
                    state: newState 
                }
            );
        }
    },
    message: function(message){
        console.log(message)
    },
    presence: function(presenceEvent){
        console.log(presenceEvent);
    }
})

pubnubDemo.subscribe({
    channels: ["demo_tutorial"],
    withPresence: true
});

// Subscribe to the presence-channel
pubnub.Presence<string>(
   channel:"demo_tutorial", 
   DisplayPresenceReturnMessage, 
   DisplayPresenceConnectStatusMessage, 
   DisplayErrorMessage);
// NOTE: DisplayPresenceReturnMessage, DisplayPresenceConnectStatusMessage and DisplayErrorMessage are callback methods

// Subscribe to the channel
pubnub.Subscribe<string>(
   channel:"demo_tutorial", 
   DisplaySubscribeReturnMessage, 
   DisplaySubscribeConnectStatusMessage, 
   DisplayErrorMessage);
// NOTE: DisplaySubscribeReturnMessage, DisplaySubscribeConnectStatusMessage and DisplayErrorMessage are callback methods

// Set the state for the channel
pubnub.SetUserState<string>(
   channel:"demo_tutorial", 
   jsonUserState='{"name":"presence-tutorial-user"}', 
   DisplayReturnMessage, 
   DisplayErrorMessage);
// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods


/***************
For all other languages,
check out the 70+ SDKs that PubNub supports
on our documentation page:
/docs
****************/

3

Unsubscribe

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 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 channel
pubnubDemo.unsubscribe({
    channels: ['demo_tutorial']
});

// Unsubcribe from the channel
pubnub.Unsubscribe<string>(
   channel:"demo_tutorial", 
   DisplayReturnMessage, 
   DisplaySubscribeConnectStatusMessage, 
   DisplaySubscribeDisconnectStatusMessage, 
   DisplayErrorMessage);
   
// NOTE: DisplayReturnMessage, DisplaySubscribeConnectStatusMessage, DisplaySubscribeDisconnectStatusMessage and DisplayErrorMessage 

// Unsubcribe from the presence-channel
pubnub.PresenceUnsubscribe<string>(
   channel:"demo_tutorial", 
   DisplayReturnMessage, 
   DisplayPresenceConnectStatusMessage, 
   DisplayPresenceDisconnectStatusMessage, 
   DisplayErrorMessage);
   
// NOTE: DisplayReturnMessage, DisplayPresenceConnectStatusMessage, DisplayPresenceDisconnectStatusMessage and DisplayErrorMessage 


/***************
For all other languages,
check out the 70+ SDKs that PubNub supports
on our documentation page:
/docs
****************/

4

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(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
pubnubDemo.hereNow(
    {
        channels: ['demo_tutorial'],
        includeState: true
    },
    function(status, response){
        console.log(response);
    }
);


// View the UUID and state objects of those currently subscribed
pubnub.HereNow<string>(
   channel:"demo_tutorial", 
   DisplayReturnMessage, 
   DisplayErrorMessage);

pubnub.HereNow<string>(
   channel:"demo_tutorial", 
   showUUID:true, 
   includeUserState:true, 
   DisplayReturnMessage, 
   DisplayErrorMessage);

// NOTE: DisplayReturnMessage and DisplayErrorMessage are callback methods


/***************
For all other languages,
check out the 70+ SDKs that PubNub supports
on our documentation page:
/docs
****************/

6

You are now a master of Presence!

With those few steps, you've built your first PubNub application with Presence!

If you haven't already, Sign Up for a free PubNub account. Then continue with our other feature guides for Access Manager and Storage & Playback to make your app more robust.

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

logos

Try PubNub Today

Connect up to 100 devices for Free