Listeners & Events
Messages, signals, files, and events are received in your application using a listener. Each type of message or event has its own handler where you implement your logic. For more information on event listeners, refer to the Listeners section of the PubNub SDK documentation.
Event Listeners
Below is an overview of each of the event listeners.
Handler | Description |
---|---|
status | Receives events related to errors and status of the client. |
message | Receives messages published to any channels subscribed by the client. |
signal | Receives signals that are sent to any channels subscribed by the client. |
presence | Receives presence events (join, leave, timeout, state-change) that are triggered on any channels subscribed by the client. |
messageAction | Receives events triggered when existing messages are annotated (by an action) for any channels subscribed by the client. |
objects | Receives all objects events triggered when a channel, channel membership, or user metadata is created, updated, or removed. |
file | Receives all file events that are emitted when a file is uploaded. Clients can either directly use the file URL to display the file in a browser or download the file. |
Adding event listeners
Once you add the listeners, they'll trigger events as the client application receives messages and other updates. These listeners should be added before you perform PubNub operations like subscribing to channels.
pubnub.addListener({
status: function(s) {
var affectedChannelGroups = s.affectedChannelGroups; // Array of channel groups affected in the operation
var affectedChannels = s.affectedChannels; // Array of channels affected in the operation
var category = s.category; //Returns PNConnectedCategory
var operation = s.operation; //Returns PNSubscribeOperation
var lastTimetoken = s.lastTimetoken; //The last timetoken used in the subscribe request, of type long.
var currentTimetoken = s.currentTimetoken; // Current timetoken in the subscribe response, to be used in the next request, of type long.
var subscribedChannels = s.subscribedChannels; // Array of all currently subscribed channels
},
message: function(m) {
// handle message
var channelName = m.channel; // The channel to which the message belongs
var channelGroup = m.subscription; // The channel group or wildcard subscription match (if exists)
var pubTT = m.timetoken; // Publish timetoken
var msg = m.message; // The Payload
var publisher = m.publisher; //The Publisher
},
presence: function(p) {
// handle presence
var action = p.action; // Can be join, leave, state-change or timeout
var channelName = p.channel; // The channel for which the message belongs
var occupancy = p.occupancy; // No. of users connected with the channel
var state = p.state; // User State
var channelGroup = p.subscription; // The channel group or wildcard subscription match (if exists)
var publishTime = p.timestamp; // Publish timetoken
var timetoken = p.timetoken; // Current timetoken
var uuid = p.uuid; // UUIDs of users who are connected with the channel
},
signal: function(s) {
// handle signal
var channelName = s.channel; // The channel for which the signal belongs
var channelGroup = s.subscription; // The channel group or wildcard subscription match (if exists)
var pubTT = s.timetoken; // Publish timetoken
var msg = s.message; // The Payload
var publisher = s.publisher; //The Publisher
},
messageAction: function(ma) {
// handle message action
var channelName = ma.channel; // The channel for which the message belongs
var publisher = ma.publisher; //The Publisher
var event = ma.message.event; // message action added or removed
var type = ma.message.data.type; // message action type
var value = ma.message.data.value; // message action value
var messageTimetoken = ma.message.data.messageTimetoken; // The timetoken of the original message
var actionTimetoken = ma.message.data.actionTimetoken; //The timetoken of the message action
},
objects: function(o) {
var channelName = o.channel; // Channel
var channelGroup = o.subscription; // Channel group
var pubTT = o.timetoken; // Publish timetoken
var event = o.message.event; // Event action (set or delete)
var type = o.message.type; // Type of metadata involved
var data = o.message.data; // Event data
},
file: function(f) {
// handle file
var channel = f.channel; // The channel
var channelGroup = f.subscription; // The channel group
var pubTT = f.timetoken; // Publish timetoken
var message = f.message; // The Message
var fileId = f.file.id; // The File Id
var fileName = f.file.name; // The File Name
var fileUrl = f.file.url //The File URL
var publisher = f.publisher; //The Publisher
}
});
// Create a new listener instance
let listener = SubscriptionListener()
// Add listener event callbacks
listener.didReceiveSubscription = { event in
switch event {
case messageReceived(message):
print("Message Received: \(message)")
case connectionStatusChanged(status):
print("Status Received: \(status)")
case presenceChanged(event):
print("Presence Received: \(presence)")
case subscribeError(PubNubError):
print("Subscription Error \(error.localizedError)")
default:
break
}
}
// Start receiving subscription events
pubnub.add(listener)
pubnub.addListener(new SubscribeCallback() {
@Override
public void status(PubNub pubnub, PNStatus status) {
switch (status.getOperation()) {
// let's combine unsubscribe and subscribe handling for ease of use
case PNSubscribeOperation:
case PNUnsubscribeOperation:
// note: subscribe statuses never have traditional
// errors, they just have categories to represent the
// different issues or successes that occur as part of subscribe
switch (status.getCategory()) {
case PNConnectedCategory:
// this is expected for a subscribe, this means there is no error or issue whatsoever
case PNReconnectedCategory:
// this usually occurs if subscribe temporarily fails but reconnects. This means
// there was an error but there is no longer any issue
case PNDisconnectedCategory:
// this is the expected category for an unsubscribe. This means there
// was no error in unsubscribing from everything
case PNUnexpectedDisconnectCategory:
// this is usually an issue with the internet connection, this is an error, handle appropriately
case PNAccessDeniedCategory:
// this means that PAM does allow this client to subscribe to this
// channel and channel group configuration. This is another explicit error
default:
// More errors can be directly specified by creating explicit cases for other
// error categories of `PNStatusCategory` such as `PNTimeoutCategory` or `PNMalformedFilterExpressionCategory` or `PNDecryptionErrorCategory`
}
case 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 the Configuration section of the SDK reference documentation.
if (status.isError()) {
// There was an error with the heartbeat operation, handle here
} else {
// heartbeat operation was successful
}
default: {
// Encountered unknown status type
}
}
}
@Override
public void message(PubNub pubnub, PNMessageResult message) {
String messagePublisher = message.getPublisher();
System.out.println("Message publisher: " + messagePublisher);
System.out.println("Message Payload: " + message.getMessage());
System.out.println("Message Subscription: " + message.getSubscription());
System.out.println("Message Channel: " + message.getChannel());
System.out.println("Message timetoken: " + message.getTimetoken());
}
@Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
}
@Override
public void signal(PubNub pubnub, PNSignalResult pnSignalResult) {
System.out.println("Signal publisher: " + signal.getPublisher());
System.out.println("Signal payload: " + signal.getMessage());
System.out.println("Signal subscription: " + signal.getSubscription());
System.out.println("Signal channel: " + signal.getChannel());
System.out.println("Signal timetoken: " + signal.getTimetoken());
}
@Override
public void user(PubNub pubnub, PNUserResult pnUserResult) {
// for Objects, this will trigger when:
// . user updated
// . user deleted
PNUser pnUser = pnUserResult.getUser(); // the user for which the event applies to
pnUserResult.getEvent(); // the event name
}
@Override
public void space(PubNub pubnub, PNSpaceResult pnSpaceResult) {
// for Objects, this will trigger when:
// . space updated
// . space deleted
PNSpace pnSpace = pnSpaceResult.getSpace(); // the space for which the event applies to
pnSpaceResult.getEvent(); // the event name
}
@Override
public void membership(PubNub pubnub, PNMembershipResult pnMembershipResult) {
// for Objects, this will trigger when:
// . user added to a space
// . user removed from a space
// . membership updated on a space
JsonElement data = pnMembershipResult.getData(); // membership data for which the event applies to
pnMembershipResult.getEvent(); // the event name
}
@Override
public void messageAction(PubNub pubnub, PNMessageActionResult pnActionResult) {
PNMessageAction pnMessageAction = pnActionResult.getAction();
System.out.println("Message action type: " + pnMessageAction.getType());
System.out.println("Message action value: " + pnMessageAction.getValue());
System.out.println("Message action uuid: " + pnMessageAction.getUuid());
System.out.println("Message action actionTimetoken: " + pnMessageAction.getActionTimetoken());
System.out.println("Message action messageTimetoken: " + pnMessageAction.getMessageTimetoken());]
System.out.println("Message action subscription: " + pnActionResult.getSubscription());
System.out.println("Message action channel: " + pnActionResult.getChannel());
System.out.println("Message action timetoken: " + pnActionResult.getTimetoken());
}
});
pubnub.SubscribeCallback += SubscribeCallbackHandler;
//Handler
void SubscribeCallbackHandler(object sender, EventArgs e) {
SubscribeEventEventArgs mea = e as SubscribeEventEventArgs;
if (mea.Status != null) {
switch (mea.Status.Category) {
case PNStatusCategory.PNUnexpectedDisconnectCategory:
case PNStatusCategory.PNTimeoutCategory:
break;
}
}
if (mea.MessageResult != null) {
Debug.Log("Channel" + mea.MessageResult.Channel);
Debug.Log("Payload" + mea.MessageResult.Payload);
Debug.Log("Publisher Id: " + mea.MessageResult.IssuingClientId);
}
if (mea.PresenceEventResult != null) {
Debug.Log("SubscribeCallback in presence" + mea.PresenceEventResult.Channel + mea.PresenceEventResult.Occupancy + mea.PresenceEventResult.Event);
}
if (mea.SignalEventResult != null) {
Debug.Log ("SubscribeCallback in SignalEventResult" + mea.SignalEventResult.Channel + mea.SignalEventResult.Payload);
}
if (mea.UserEventResult != null) {
Debug.Log(mea.UserEventResult.Name);
Debug.Log(mea.UserEventResult.Email);
Debug.Log(mea.UserEventResult.ExternalID);
Debug.Log(mea.UserEventResult.ProfileURL);
Debug.Log(mea.UserEventResult.UserID);
Debug.Log(mea.UserEventResult.ETag);
Debug.Log(mea.UserEventResult.ObjectsEvent);
}
if (mea.SpaceEventResult != null) {
Debug.Log(mea.SpaceEventResult.Name);
Debug.Log(mea.SpaceEventResult.Description);
Debug.Log(mea.SpaceEventResult.SpaceID);
Debug.Log(mea.SpaceEventResult.ETag);
Debug.Log(mea.SpaceEventResult.ObjectsEvent);
}
if (mea.MembershipEventResult != null) {
Debug.Log(mea.MembershipEventResult.UserID);
Debug.Log(mea.MembershipEventResult.Description);
Debug.Log(mea.MembershipEventResult.SpaceID);
Debug.Log(mea.MembershipEventResult.ObjectsEvent);
}
if (mea.MessageActionsEventResult != null) {
Debug.Log(mea.MessageActionsEventResult.Channel);
if(mea.MessageActionsEventResult.Data!=null){
Debug.Log(mea.MessageActionsEventResult.Data.ActionTimetoken);
Debug.Log(mea.MessageActionsEventResult.Data.ActionType);
Debug.Log(mea.MessageActionsEventResult.Data.ActionValue);
Debug.Log(mea.MessageActionsEventResult.Data.MessageTimetoken);
Debug.Log(mea.MessageActionsEventResult.Data.UUID);
}
Debug.Log(mea.MessageActionsEventResult.MessageActionsEvent);
Debug.Log(mea.MessageActionsEventResult.Subscription);
}
}
pubnub.AddListener(new SubscribeCallbackExt(
// Messages
delegate (Pubnub pnObj, PNMessageResult<object> pubMsg)
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(pubMsg));
var channelName = pubMsg.Channel;
var channelGroupName = pubMsg.Subscription;
var pubTT = pubMsg.Timetoken;
var msg = pubMsg.Message;
var publisher = pubMsg.Publisher;
},
// Presence
delegate (Pubnub pnObj, PNPresenceEventResult presenceEvnt)
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(presenceEvnt));
var action = presenceEvnt.Event; // Can be join, leave, state-change or timeout
var channelName = presenceEvnt.Channel; // The channel for which the message belongs
var occupancy = presenceEvnt.Occupancy; // No. of users connected with the channel
var state = presenceEvnt.State; // User State
var channelGroupName = presenceEvnt.Subscription; // The channel group or wildcard subscription match (if exists)
var publishTime = presenceEvnt.Timestamp; // Publish timetoken
var timetoken = presenceEvnt.Timetoken; // Current timetoken
var uuid = presenceEvnt.Uuid; // UUIDs of users who are connected with the channel
},
// Signals
delegate (Pubnub pnObj, PNSignalResult<object> signalMsg)
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(signalMsg));
var channelName = signalMsg.Channel; // The channel for which the signal belongs
var channelGroupName = signalMsg.Subscription; // The channel group or wildcard subscription match (if exists)
var pubTT = signalMsg.Timetoken; // Publish timetoken
var msg = signalMsg.Message; // The Payload
var publisher = signalMsg.Publisher; //The Publisher
},
// Objects
delegate (Pubnub pnObj, PNObjectEventResult objectEventObj)
{
var channelName = objectEventObj.Channel; // Channel
var channelMetadata = objectEventObj.ChannelMetadata; //Channel Metadata
var uidMetadata = objectEventObj.UuidMetadata; // UUID metadata
var evnt = objectEventObj.Event; // Event
var type = objectEventObj.Type; // Event type
if (objectEventObj.Type == "uuid") { /* got uuid metadata related event. */ }
else if (objectEventObj.Type == "channel") { /* got channel metadata related event. */ }
else if (objectEventObj.Type == "membership") { /* got membership related event. */ }
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(objectEventObj));
},
// Message actions
delegate (Pubnub pnObj, PNMessageActionEventResult msgActionEvent)
{
var channelName = msgActionEvent.Channel; // The channel for which the message belongs
var msgEvent = msgActionEvent.Action; // message action added or removed
var msgActionType = msgActionEvent.Event; // message action type
var messageTimetoken = msgActionEvent.MessageTimetoken; // The timetoken of the original message
var actionTimetoken = msgActionEvent.ActionTimetoken; //The timetoken of the message action
},
// Files
delegate (Pubnub pnObj, PNFileEventResult fileEvent)
{
//handle file message event
var channelName = fileEvent.Channel;
var chanelGroupName = fileEvent.Subscription;
var fieldId = (fileEvent.File != null) ? fileEvent.File.Id : null;
var fileName = (fileEvent.File != null) ? fileEvent.File.Name : null;
var fileUrl = (fileEvent.File != null) ? fileEvent.File.Url : null;
var fileMessage = fileEvent.Message;
var filePublisher = fileEvent.Publisher;
var filePubTT = fileEvent.Timetoken;
},
// Status
delegate (Pubnub pnObj, PNStatus pnStatus)
{
Console.WriteLine("{0} {1} {2}", pnStatus.Operation, pnStatus.Category, pnStatus.StatusCode);
var affectedChannelGroups = pnStatus.AffectedChannelGroups; // The channel groups affected in the operation, of type array.
var affectedChannels = pnStatus.AffectedChannels; // The channels affected in the operation, of type array.
var category = pnStatus.Category; //Returns PNConnectedCategory
var operation = pnStatus.Operation; //Returns PNSubscribeOperation
}
));
import (
pubnub "github.com/pubnub/go"
)
listener := pubnub.NewListener()
go func() {
for {
select {
case signal := <-listener.Signal:
//Channel
fmt.Println(signal.Channel)
//Subscription
fmt.Println(signal.Subscription)
//Payload
fmt.Println(signal.Message)
//Publisher ID
fmt.Println(signal.Publisher)
//Timetoken
fmt.Println(signal.Timetoken)
case status := <-listener.Status:
switch status.Category {
case pubnub.PNDisconnectedCategory:
// this is the expected category for an unsubscribe. This means there
// was no error in unsubscribing from everything
case pubnub.PNConnectedCategory:
// this is expected for a subscribe, this means
// there is no error or issue whatsoever
case pubnub.PNReconnectedCategory:
// this usually occurs if subscribe temporarily fails but reconnects.
// This means there was an error but there is no longer any issue
case pubnub.PNAccessDeniedCategory:
// this means that PAM does allow this client to subscribe to this
// channel and channel group configuration. This is another explicit error
}
case message := <-listener.Message:
//Channel
fmt.Println(message.Channel)
//Subscription
fmt.Println(message.Subscription)
//Payload
fmt.Println(message.Message)
//Publisher ID
fmt.Println(message.Publisher)
//Timetoken
fmt.Println(message.Timetoken)
case presence := <-listener.Presence:
fmt.Println(presence.Event)
//Channel
fmt.Println(presence.Channel)
//Subscription
fmt.Println(presence.Subscription)
//Timetoken
fmt.Println(presence.Timetoken)
//Occupancy
fmt.Println(presence.Occupancy)
case uuidEvent := <-listener.UUIDEvent:
fmt.Println(fmt.Sprintf("uuidEvent.Channel: %s", uuidEvent.Channel))
fmt.Println(fmt.Sprintf("uuidEvent.SubscribedChannel: %s", uuidEvent.SubscribedChannel))
fmt.Println(fmt.Sprintf("uuidEvent.Event: %s", uuidEvent.Event))
fmt.Println(fmt.Sprintf("uuidEvent.UUID: %s", uuidEvent.UUID))
fmt.Println(fmt.Sprintf("uuidEvent.Description: %s", uuidEvent.Description))
fmt.Println(fmt.Sprintf("uuidEvent.Timestamp: %s", uuidEvent.Timestamp))
fmt.Println(fmt.Sprintf("uuidEvent.Name: %s", uuidEvent.Name))
fmt.Println(fmt.Sprintf("uuidEvent.ExternalID: %s", uuidEvent.ExternalID))
fmt.Println(fmt.Sprintf("uuidEvent.ProfileURL: %s", uuidEvent.ProfileURL))
fmt.Println(fmt.Sprintf("uuidEvent.Email: %s", uuidEvent.Email))
fmt.Println(fmt.Sprintf("uuidEvent.Updated: %s", uuidEvent.Updated))
fmt.Println(fmt.Sprintf("uuidEvent.ETag: %s", uuidEvent.ETag))
fmt.Println(fmt.Sprintf("uuidEvent.Custom: %v", uuidEvent.Custom))
case channelEvent := <-listener.ChannelEvent:
fmt.Println(fmt.Sprintf("channelEvent.Channel: %s", channelEvent.Channel))
fmt.Println(fmt.Sprintf("channelEvent.SubscribedChannel: %s", channelEvent.SubscribedChannel))
fmt.Println(fmt.Sprintf("channelEvent.Event: %s", channelEvent.Event))
fmt.Println(fmt.Sprintf("channelEvent.Channel: %s", channelEvent.Channel))
fmt.Println(fmt.Sprintf("channelEvent.Description: %s", channelEvent.Description))
fmt.Println(fmt.Sprintf("channelEvent.Timestamp: %s", channelEvent.Timestamp))
fmt.Println(fmt.Sprintf("channelEvent.Updated: %s", channelEvent.Updated))
fmt.Println(fmt.Sprintf("channelEvent.ETag: %s", channelEvent.ETag))
fmt.Println(fmt.Sprintf("channelEvent.Custom: %v", channelEvent.Custom))
case membershipEvent := <-listener.MembershipEvent:
fmt.Println(fmt.Sprintf("membershipEvent.Channel: %s", membershipEvent.Channel))
fmt.Println(fmt.Sprintf("membershipEvent.SubscribedChannel: %s", membershipEvent.SubscribedChannel))
fmt.Println(fmt.Sprintf("membershipEvent.Event: %s", membershipEvent.Event))
fmt.Println(fmt.Sprintf("membershipEvent.Channel: %s", membershipEvent.Channel))
fmt.Println(fmt.Sprintf("membershipEvent.UUID: %s", membershipEvent.UUID))
fmt.Println(fmt.Sprintf("membershipEvent.Description: %s", membershipEvent.Description))
fmt.Println(fmt.Sprintf("membershipEvent.Timestamp: %s", membershipEvent.Timestamp))
fmt.Println(fmt.Sprintf("membershipEvent.Custom: %v", membershipEvent.Custom))
case messageActionsEvent := <-listener.MessageActionsEvent:
fmt.Println(fmt.Sprintf("messageActionsEvent.Channel: %s", messageActionsEvent.Channel))
fmt.Println(fmt.Sprintf("messageActionsEvent.SubscribedChannel: %s", messageActionsEvent.SubscribedChannel))
fmt.Println(fmt.Sprintf("messageActionsEvent.Event: %s", messageActionsEvent.Event))
fmt.Println(fmt.Sprintf("messageActionsEvent.Data.ActionType: %s", messageActionsEvent.Data.ActionType))
fmt.Println(fmt.Sprintf("messageActionsEvent.Data.ActionValue: %s", messageActionsEvent.Data.ActionValue))
fmt.Println(fmt.Sprintf("messageActionsEvent.Data.ActionTimetoken: %s", messageActionsEvent.Data.ActionTimetoken))
fmt.Println(fmt.Sprintf("messageActionsEvent.Data.MessageTimetoken: %s", messageActionsEvent.Data.MessageTimetoken))
case file := <-listener.File:
fmt.Println(fmt.Sprintf("file.File.PNMessage.Text: %s", file.File.PNMessage.Text))
fmt.Println(fmt.Sprintf("file.File.PNFile.Name: %s", file.File.PNFile.Name))
fmt.Println(fmt.Sprintf("file.File.PNFile.ID: %s", file.File.PNFile.ID))
fmt.Println(fmt.Sprintf("file.File.PNFile.URL: %s", file.File.PNFile.URL))
fmt.Println(fmt.Sprintf("file.Channel: %s", file.Channel))
fmt.Println(fmt.Sprintf("file.Timetoken: %d", file.Timetoken))
fmt.Println(fmt.Sprintf("file.SubscribedChannel: %s", file.SubscribedChannel))
fmt.Println(fmt.Sprintf("file.Publisher: %s", file.Publisher))
}
}
}
Listener's class should conform to PNEventsListener
protocol to have access to available callbacks.
// Adding listener.
[pubnub addListener:self];
// Callbacks listed below.
- (void)client:(PubNub *)pubnub didReceiveMessage:(PNMessageResult *)message {
NSString *channel = message.data.channel; // Channel on which the message has been published
NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSNumber *timetoken = message.data.timetoken; // Publish timetoken
id msg = message.data.message; // Message payload
NSString *publisher = message.data.publisher; // Message publisher
}
- (void)client:(PubNub *)pubnub didReceiveSignal:(PNSignalResult *)signal {
NSString *channel = message.data.channel; // Channel on which the signal has been published
NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSNumber *timetoken = message.data.timetoken; // Signal timetoken
id msg = message.data.message; // Signal payload
NSString *publisher = message.data.publisher; // Signal publisher
}
- (void)client:(PubNub *)pubnub didReceiveMessageAction:(PNMessageActionResult *)action {
NSString *channel = action.data.channel; // Channel on which the message has been published
NSString *subscription = action.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSString *event = action.data.event; // Can be: added or removed
NSString *type = action.data.action.type; // Message action type
NSString *value = action.data.action.value; // Message action value
NSNumber *messageTimetoken = action.data.action.messageTimetoken; // Timetoken of the original message
NSNumber *actionTimetoken = action.data.action.actionTimetoken; // Timetoken of the message action
NSString *uuid = action.data.action.uuid; // UUID of user which added / removed message action
}
- (void)client:(PubNub *)pubnub didReceivePresenceEvent:(PNPresenceEventResult *)event {
NSString *channel = message.data.channel; // Channel on which presence changes
NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSString *presenceEvent = event.data.presenceEvent; // Can be: join, leave, state-change, timeout or interval
NSNumber *occupancy = event.data.presence.occupancy; // Number of users subscribed to the channel (not available for state-change event)
NSNumber *timetoken = event.data.presence.timetoken; // Presence change timetoken
NSString *uuid = event.data.presence.uuid; // UUID of user for which presence change happened
// Only for 'state-change' event
NSDictionary *state = event.data.presence.state; // User state (only for state-change event)
// Only for 'interval' event
NSArray<NSString *> *join = event.data.presence.join; // UUID of users which recently joined channel
NSArray<NSString *> *leave = event.data.presence.leave; // UUID of users which recently leaved channel
NSArray<NSString *> *timeout = event.data.presence.timeout; // UUID of users which recently timed out on channel
}
- (void)client:(PubNub *)pubnub didReceiveObjectEvent:(PNObjectEventResult *)event {
NSString *channel = event.data.channel; // Channel to which the event belongs
NSString *subscription = event.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSString *event = event.data.event; // Can be: set or delete
NSString *type = event.data.type; // Entity type: channel, uuid or membership
NSNumber *timestamp = event.data.timestamp; // Event timestamp
PNChannelMetadata *channelMetadata = event.data.channelMetadata; // Updated channel metadata (only for channel entity type)
PNUUIDMetadata *uuidMetadata = event.data.uuidMetadata; // Updated channel metadata (only for uuid entity type)
PNMembership *membership = event.data.membership; // Updated channel metadata (only for membership entity type)
}
- (void)client:(PubNub *)pubnub didReceiveFileEvent:(PNFileEventResult *)event {
NSString *channel = event.data.channel; // Channel to which file has been uploaded
NSString *subscription = event.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
id message = event.data.message; // Message added for uploaded file
NSString *publisher = event.data.publisher; // UUID of file uploader
NSURL *fileDownloadURL = event.data.file.downloadURL; // URL which can be used to download file
NSString *fileIdentifier = event.data.file.identifier; // Unique file identifier
NSString *fileName = event.data.file.name; // Name with which file has been stored remotely
}
- (void)client:(PubNub *)pubnub didReceiveStatus:(PNStatus *)status {
PNStatusCategory category = status.category; // One of PNStatusCategory fields to identify status of operation processing
PNOperationType operation = status.operation; // One of PNOperationType fields to identify for which operation status received
BOOL isError = status.isError; // Whether any kind of error happened.
NSInteger statusCode = status.statusCode; // Related request processing status code
BOOL isTLSEnabled = status.isTLSEnabled; // Whether secured connection enabled
NSString *uuid = status.uuid; // UUID which configured for passed client
NSString *authKey = status.authKey; // Auth key configured for passed client
NSString *origin = status.origin; // Origin against which request has been sent
NSURLRequest *clientRequest = status.clientRequest; // Request which has been used to send last request (may be nil)
BOOL willAutomaticallyRetry = status.willAutomaticallyRetry; // Whether client will try to perform automatic retry
// Following is available when operation == PNSubscribeOperation, because status is PNSubscribeStatus instance in this case
PNSubscribeStatus *subscribeStatus = (PNSubscribeStatus *)status;
NSNumber *currentTimetoken = subscribeStatus.currentTimetoken; // Timetoken which has been used for current subscribe request
NSNumber *lastTimeToken = subscribeStatus.lastTimeToken; // Timetoken which has been used for previous subscribe request
NSArray<NSString *> *subscribedChannels = subscribeStatus.subscribedChannels; // List of channels on which client currently subscribed
NSArray<NSString *> *subscribedChannelGroups = subscribeStatus.subscribedChannelGroups; // List of channel groups on which client currently subscribed
NSString *channel = subscribeStatus.data.channel; // Name of channel for which status has been received
NSString *subscription = subscribeStatus.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
NSNumber *timetoken = subscribeStatus.data.timetoken; // Timetoken at which event arrived
NSDictionary *userMetadata = subscribeStatus.data.userMetadata; // Metadata / envelope which has been passed along with event
// Following is available when isError == YES, because status is PNErrorStatus instance in this case
PNErrorStatus *errorStatus = (PNErrorStatus *)status;
id associatedObject = errorStatus.associatedObject; // Data which may contain related information (not decrypted message for example)
NSArray<NSString *> *erroredChannels = errorStatus.errorData.channels; // List of channels for which error reported (mostly because of PAM)
NSArray<NSString *> *erroredChannelGroups = errorStatus.errorData.channelGroups; // List of channel groups for which error reported (mostly because of PAM)
NSString *errorInformation = errorStatus.errorData.information; // Stringified information about error
id errorData = errorStatus.errorData.data; // Additional error information from PubNub service
}
Removing event listeners
Use pubnub.removeListener()
(it's token.cancel()
in Swift) to remove one or more listeners.
var existingListener = {
message: function() {
}
}
pubnub.removeListener(existingListener)
In Swift, you can remove the SubscriptionListener
through the ListenerToken
by either calling token.cancel()
or by letting it be automatically removed as an autoreleased object.
SubscribeCallback subscribeCallback = new SubscribeCallback() {
@Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
}
};
pubnub.addListener(subscribeCallback);
// some time later
pubnub.removeListener(subscribeCallback);
pubnub.SubscribeCallback -= SubscribeCallbackHandler;
pubnub.RemoveListener(listenerSubscribeCallack);
pn.RemoveListener(listener)
Events
Once you add the listeners, they'll trigger events as the client application receives messages and other updates. Below is the list of events that are generated by PubNub.
Status Events
Status events are generated to indicate the success and failure status of operations. To handle error events, enable the status
listeners in your code. You can access the status category by using status.category
property.
The Swift SDK has different status events listed here.
Event Types:
Event | Operation | Description |
---|---|---|
PNBadRequestCategory | Publish | SDK sends PNBadRequestCategory when some parameter is missing like message, channel, subscribe key, publish key. |
PNUnexpectedDisconnectCategory | Publish | The SDK isn't able to reach the PubNub Data Stream Network because the machine or device aren't connected to Internet or this has been lost, your ISP (Internet Service Provider) is having to troubles or perhaps or the SDK is behind of a proxy. |
PNTimeoutCategory | Publish | Processing has failed because of request time out. |
PNNetworkUpCategory | Subscribe | SDK detected that network is online. |
PNNetworkDownCategory | Subscribe | The SDK announces this when connection isn't available or this isn't able to reach the PubNub Data Stream Network. |
PNNetworkIssuesCategory | Subscribe | A subscribe event experienced an exception when running. The SDK isn't being to able reach the PubNub Data Stream Network because the machine or device aren't connected to Internet or this has been lost, your ISP (Internet Service Provider) is having to troubles or perhaps or the SDK is behind of a proxy. |
PNReconnectedCategory | Subscribe | SDK has reconnected to PubNub. |
PNConnectedCategory | Subscribe | SDK subscribed with a mix of channels and channel groups (fired every time the channel / channel group mix changed). |
PNAccessDeniedCategory | Subscribe | PAM permission failure. |
PNMalformedResponseCategory | Subscribe | JSON parsing crashed. |
PNBadRequestCategory | Subscribe | The server responded with bad response because the request is malformed. |
PNDecryptionErrorCategory | Subscribe | If using decryption strategies and the decryption fails. |
PNTimeoutCategory | Subscribe | Failure to establish connection due to timeout. |
PNRequestMessageCountExceedCategory | Subscribe | The SDK announces this error if requestMessageCountThreshold is set and the number of messages arrived from PubNub (in memory cache messages) are greater than this. |
PNUnknownCategory | Subscribe | Returned when the subscriber gets a non 200 HTTP response code from the server. |
Event Sample:
{
"category": "PNConnectedCategory",
"operation": "PNSubscribeOperation",
"affectedChannels": ["my_channel_1"],
"subscribedChannels": ["my_channel_1"],
"affectedChannelGroups": [],
"lastTimetoken": "14974492380756600",
"currentTimetoken": "14974492384874375"
}
Network Up/Down Events
Most of the PubNub SDKs automatically reconnect if you enable the reconnection policy flags when you initialize the PubNub instance.
The JavaScript SDK doesn't ping at regular intervals, in an attempt to conserve resources. Instead, it relies on browser networking events for reconnection if you enable the autoNetworkDetection flag. To re-establish a connection, call pubnub.reconnect()
when you receive the PNNetworkUpCategory
event.
Message Events
The following events are generated when messages are received on channels or channel groups that are subscribed by the clients.
Event Sample:
{
"actualChannel": null,
"channel": "my_channel_1",
"message": "Hello World!",
"publisher": "pn-58e1a647-3e8a-4c7f-bfa4-e007ea4b2073",
"subscribedChannel": "my_channel_1",
"subscription": null,
"timetoken": "14966804541029440"
}
Signal Events
The following events are generated when signals are received on channels or channel groups that are subscribed by the clients.
{
"actualChannel": null,
"channel": "my_channel_1",
"message": "typing_on",
"publisher": "pn-58e1a647-3e8a-4c7f-bfa4-e007ea4b2073",
"subscribedChannel": "my_channel_1",
"subscription": null,
"timetoken": "14966804541029440"
}
Presence Events
The following presence events are generated when users connect or disconnect from channels.
Event Types:
Event | 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 severed 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 sample:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "join",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user1",
"timestamp": 1511946669
}
Leave event sample:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "leave",
"timetoken": "15119446002445794",
"occupancy": 1,
"uuid": "user1",
"timestamp": 1511944600
}
Timeout event sample:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "timeout",
"timetoken": "15119519897494311",
"occupancy": 3,
"uuid": "user1",
"timestamp": 1511951989
}
Custom state change event sample:
{
"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 sample:
{
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"action": "interval",
"timetoken": "15119477895378127",
"occupancy": 2,
"timestamp": 1511947739
}
Message Action Events
Message action events are published to notify clients when Message Actions are added to or removed from messages. To receive these events, clients should be subscribed to the channel, and add a messageAction
listener.
Event | Description |
---|---|
Message Action Added | Generated when a message action is added to a message. |
Message Action Removed | Generated when a message action is removed from a message. |
Message Action Added event sample:
{
"channel":"my_channel",
"subscription":null,
"timetoken":"15871508399473609",
"publisher":"user-1",
"message":{
"source":"actions",
"version":"1.0",
"action":"added",
"data":{
"type":"reaction",
"value":"smiley_face",
"messageTimetoken":"15632184115444390",
"actionTimetoken":"15632184115444394"
}
}
}
Message Action Removed event sample:
{
"channel":"my_channel",
"subscription":null,
"timetoken":"15871508399473609",
"publisher":"user-1",
"message":{
"source":"actions",
"version":"1.0",
"action":"removed",
"data":{
"type":"reaction",
"value":"smiley_face",
"messageTimetoken":"15632184115444390",
"actionTimetoken":"15632184115444394"
}
}
}
Objects Events
Objects events are generated when a user metadata, channel metadata or memberships are set or removed from the objects database. Object events are disabled by default on new keys. You can enable or disable these events from your key settings in the Admin Portal.
When you set the metadata on a user, PubNub creates a channel (named for that user's UUID) where the metadata events are emitted. In addition, if the user is a member of one or more channels, those channels also receive events for that specific user.
When you add, remove, or update membership metadata, the events are emitted to the corresponding UUID channel and the specific channel that was impacted by the modification. Your application can subscribe to said channels to receive metadata events and act upon them.
Event | Description | Publish location |
---|---|---|
User Metadata Set | User metadata is set or updated. | These events are published on {uuid} and {channel} memberships for the user. |
User Metadata Deleted | User metadata is deleted. | These events are published on {uuid} and {channel} memberships for the user. |
Channel Metadata Set | Channel metadata is set or updated. | These events are published on {channel}. |
Channel Metadata Deleted | Channel metadata is deleted. | These events are published on {channel}. |
Membership Set | User-channel membership is created or updated. | These events are published on {uuid} and {channel}. |
Membership Removed | User-channel membership is deleted. | These events are published on {uuid} and {channel}. |
User Metadata Set event sample:
{
"channel":"ch-1",
"message":{
"event":"set",
"type":"uuid",
"data":{
"id":"uuid-1",
"name":"John Doe",
"email":"john@email.com",
"updated":"2020-06-10T16:22:11.035374Z",
"eTag":"AY39mJKK//C0VA"
}
},
"subscription":null,
"timetoken":"15119446002445794"
}
Channel Metadata Set event sample:
{
"channel":"ch-1",
"message":{
"event":"set",
"type":"channel",
"data":{
"id":"ch-1",
"name":"main channel",
"description":"A meeting room for the team",
"updated":"2020-02-20T23:11:20.893755"
}
},
"subscription":null,
"timetoken":"15119446002445794"
}
Membership Set event sample:
{
"channel":"ch-1",
"message":{
"event":"set",
"type":"membership",
"data":{
"channel":{
"id":"ch-1"
},
"uuid":{
"id":"uuid-1"
},
"custom":null,
"updated":"2020-04-17T19:13:59.40962853Z",
"eTag":"AY39mJKK//C0VA"
}
},
"subscription":null,
"timetoken":"15119446002445794"
}
File Events
File events are generated when a file is uploaded. Clients can either directly use the file URL to display the file in a browser or download the file.
File Received event sample:
{
"channel":"demo-channel",
"message": null,
"subscription": null,
"timetoken":"15958540412130227",
"publisher":"javascript-fileUploadApiV1-tests-main",
"file":{
"id":"t35t-f1l3-1d",
"name":"testFile.json",
"url":"example.com/v1/files/your-key/channels/demo-channel/files/t35t-f1l3-1d/testFile.json"
}
}