Realtime Client Library API

Channels and Messages

The Ably Realtime service organizes the message traffic within applications into named channels. Channels are the “unit” of message distribution; clients attach to channels to subscribe to messages, and every message published to a unique channel is broadcast by Ably to all subscribers. This scalable and resilient messaging pattern is commonly called pub/sub.

Getting started

The Ably Realtime client library provides a straightforward API for publishing and subscribing to messages on a channel. If the channel does not exist at the time the client is attached, a channel will be created in the Ably system immediately.

var realtime = new Ably.Realtime('xVLyHw.6JDtVg:CVFvdGz9mr5th-OX');
var channel = realtime.channels.get('gut-dye-man');
channel.subscribe(function(message) {
  alert('Received: ' + message.data);
});
channel.publish('example', 'message data');
var Ably = require('ably');
var realtime = new Ably.Realtime('xVLyHw.6JDtVg:CVFvdGz9mr5th-OX');
var channel = realtime.channels.get('gut-dye-man');
channel.subscribe(function(message) {
  alert("Received: "  message.data);
});
channel.publish("example", "message data");
realtime = Ably::Realtime.new('xVLyHw.6JDtVg:CVFvdGz9mr5th-OX')
channel = realtime.channels.get('gut-dye-man')
channel.subscribe do |message|
  puts "Received: #{message.data}"
end
channel.publish 'example', 'message data'
AblyRealtime realtime = new AblyRealtime("xVLyHw.6JDtVg:CVFvdGz9mr5th-OX");
Channel channel = realtime.channels.get("gut-dye-man");
channel.subscribe(new MessageListener() {
  @Override
  public void onMessage(Message message) {
    System.out.println("New messages arrived. " + message.name);
  }
});
channel.publish("example", "message data");
AblyRealtime realtime = new AblyRealtime("xVLyHw.6JDtVg:CVFvdGz9mr5th-OX");
var channel = realtime.Channels.Get("gut-dye-man");
channel.Subscribe(message => {
  Console.WriteLine($"Message: {message.name}:{message.data} received")
});
channel.Publish("example", "message data");
ARTRealtime *realtime = [[ARTRealtime alloc] initWithKey:@"xVLyHw.6JDtVg:CVFvdGz9mr5th-OX"];
ARTRealtimeChannel *channel = [realtime.channels get:@"gut-dye-man"];
[channel subscribe:^(ARTMessage *message) {
    NSLog(@"Received: %@", message.data);
}];
[channel publish:@"example" data:@"message data"];
let realtime = ARTRealtime(key: "xVLyHw.6JDtVg:CVFvdGz9mr5th-OX")
let channel = realtime.channels.get("gut-dye-man")
channel.subscribe { message in
    print("Received: \(message.data)")
}
channel.publish("example", data: "message data")

If you would prefer to just dive into code and see some examples of how to use channels and messages, then we recommend you take a look at our Realtime tutorials.

Channels

In order to publish, subscribe to, or be present on a channel, you must first obtain a channel instance and then attach to that channel. In most instances, as a convenience, it is unnecessary to explicitly attach a channel as it will implicitly attached when performing any operation on the channel such as publishing or subscribing.

Obtaining a channel instance

A Channel object is a reference to a single channel. A channel instance is obtained from the channels collection of the Realtime::ClientRealtimeARTRealtimeAblyRealtime instance, and is uniquely identified by its unicode string name. Find out more about channel naming

var channel = realtime.channels.get('channelName');
var channel = realtime.channels.get('channelName');
Channel channel = realtime.channels.get("channelName");
var channel = realtime.Channels.Get("channelName");
channel = realtime.channels.get('channelName')
ARTRealtimeChannel *channel = [realtime.channels get:@"channelName"];
let channel = realtime.channels.get("channelName")

Setting channel options and encryption

A set of channel options may also be passed to configure a channel for encryption. Find out more about symmetric message encryption.

Ably.Realtime.Crypto.generateRandomKey(function(err, key) {
  var options = { cipher: { key: key } };
  var channel = realtime.channels.get('channelName', options);
});
Ably.Realtime.Crypto.generateRandomKey(function(err, key) {
  var options = { cipher: { key: key } };
  var channel = realtime.channels.get('channelName', options);
});
CipherParams params = Crypto.getDefaultParams(key);
ChannelOptions options = new ChannelOptions();
options.encrypted = true;
options.cipherParams = params;
Channel channel = realtime.channels.get("channelName", options);
byte[] key = Crypto.GenerateRandomKey();
var cipherParams = Crypto.GetDefaultParams(key);
var channelOpts = new ChannelOptions(cipherParams);
var encryptedChannel = realtime.Channels.Get("channelName", channelOpts);
key = Ably::Util::Crypto.generate_random_key
options = { cipher: { key: key } }
channel = realtime.channels.get('channelName', options)
NSData *key = [ARTCrypto generateRandomKey];
ARTChannelOptions *options = [[ARTChannelOptions alloc] initWithCipherKey:key];
ARTRealtimeChannel *channel = [realtime.channels get:@"channelName" options:options];
let key = ARTCrypto.generateRandomKey()
let options = ARTChannelOptions(cipherKey: key)
let channel = realtime.channels.get("channelName", options: options)

Channel lifecycle

Channels are not pre-configured or provisioned by Ably in advance; they are created on demand when clients attach, and remain active until such time that there are no remaining attached clients. Within the dashboard for your app however, you can pre-configure one or more channel namespaces (i.e. name prefixes), and associate different attributes and access rights with those namespaces. Find out more about channel namespaces.

The following example explicitly attaches to a channel, which results in the channel being provisioned in Ably’s global realtime cluster. This channel will remain available globally until there are no more clients attached to the channel:

realtime.channels.get('chatroom').attach(function(err) {
  console.log('"chatroom" exists and is now available globally in every data center');
});
realtime.channels.get('chatroom').attach(function(err) {
  console.log('"chatroom" exists and is now available globally in every data center');
});
realtime.channels.get('chatroom').attach do |channel|
  puts "'chatroom' exists and is now available globally in every data center"
end
Channel channel = realtime.channels.get("chatroom");
channel.on(new ChannelStateListener() {
  @Override
  public void onChannelStateChanged(ChannelStateChange state) {
    switch (state.current) {
      case attached: {
        System.out.println("'chatroom' exists and is now available globally");
      }
    }
  }
});
var channel = realtime.Channels.Get("chatroom");
channel.Attach((success, error) => {
  Console.WriteLine("'chatroom' exists and is now available globally");
});
[[realtime.channels get:@"chatroom" options:options] attach:^(ARTErrorInfo *error) {
  NSLog(@"'chatroom' exists and is now available globally in every data center");
}];
realtime.channels.get("chatroom").attach { error in
  print("'chatroom' exists and is now available globally in every data center")
}

Clients attach to a channel in order to participate on that channel in any way (either to publish, subscribe, or be present on the channel).

Implicit attach

Although the attach operation can be initiated explicitly by a client, it is more common for the client to perform a publish or subscribe operation, and the client library will initiate the attach if the channel is not already attached. The client library allows clients to begin publishing messages to a channel as soon as the channel has been created, and messages are queued until such time as the attach has succeeded or failed.

var channel = realtime.channels.get('chatroom');
channel.subscribe('action', function(message) { // implicit attach
  console.log('Message received '' + message.data);
});
channel.publish('action', 'boom!');
var channel = realtime.channels.get('chatroom');
channel.subscribe('action', function(message) { // implicit attach
  console.log('Message received '' + message.data);
});
channel.publish('action', 'boom!');
channel = realtime.channels.get('chatroom')
channel.subscribe('action') do |message| # implicit attach
  puts "Message received: #{message}";
end
channel.publish 'action', 'boom!'
Channel channel = realtime.channels.get("chatroom");
/* Implicit attach when subscribing */
channel.subscribe(new MessageListener() {
  @Override
  public void onMessage(Message message) {
    System.out.println("Message received: " + message.data);
  }
});
channel.publish("action", "boom!");
var channel = realtime.Channels.Get("chatroom");
channel.Subscribe(message => Console.WriteLine("Message received:" + message.data));
channel.Publish("action", "boom");
ARTRealtimeChannel *channel = [realtime.channels get:@"chatroom" options:options];
[channel subscribe:@"action" callback:^(ARTMessage *message) {
    NSLog(@"Message received: %@", message.data);
}]
[channel publish:@"action" data:@"boom!"];
let channel = realtime.channels.get("chatroom")
channel.subscribe("action") { message in
    print("Message received: \(message.data)")
}
channel.publish("action", data: "boom!")

Normally, errors in attaching to a channel are communicated through the attach callback. For implicit attaches (and other cases where a channel is attached or reattached automatically, e.g. following the library reconnecting after a period in the suspended state), there is no callback, so if you want to know what happens, you’ll need to listen for channel state changes.

Channel states

A channel can exist in any of the following states:

initialized
A Channel object having this state has been initialized but no attach has yet been attempted
attaching
An attach has been initiated by sending a request to Ably. This is a transient state; it will be followed either by a transition to attached, suspended, or failed
attached
Attach has succeeded. In the attached state a client may publish and subscribe to messages, or be present
detaching
A detach has been initiated on the attached Channel by sending a request to Ably. This is a transient state; it will be followed either by a transition to detached or failed
detached
The Channel, having previously been attached, has been detached by the user
suspended
The Channel, having previously been attached, has lost continuity, usually due to the client being disconnected from Ably for more than two minutes. It will automatically attempt to reattach as soon as connectivity is restored
failed
An indefinite failure condition. This state is entered if a Channel error has been received from the Ably service (such as an attempt to attach without the necessary access rights)

Listening for state changes

The Channel object is an EventEmitter and emits an event whose name is the new state whenever there is a channel state change. Listeners are passed a ChannelStateChange object in the first argument. This contains the current and previous states, a resumed flag which indicated whether message continuity on this channel is preserved (from the last time that the channel was attached), and (sometimes) a reason for the state change. As with all events from an EventEmitter in the Ably library, this within the listener function is a reference to an event object whose event property is the name of the event that fired. This allows a listener to listen for all events with a single registration and know, which event fired when it is entered.

The Channel object can also emit one event that is not a state change: an update event. This happens when there’s a change to channel conditions for which the channel state doesn’t change. For example, a partial loss of message continuity on a channel (typically after a resume) for which the channel state remains attached would lead to an update event being emitted, with both current and previous set to “attached”, and the resumed flag set to false. So if you get such an event, you’ll know there may be messages you’ve missed on the channel, and if necessary you can use the History api to retrieve them.

channel.on('attached', function(stateChange) {
  console.log('channel ' + channel.name + ' is now attached');
  console.log('Message continuity on this channel ' + \
    (stateChange.resumed ? 'was' : 'was not') + ' preserved');
});
channel.on('attached', function(stateChange) {
  console.log('channel ' + channel.name + ' is now attached');
  console.log('Message continuity on this channel ' + \
    (stateChange.resumed ? 'was' : 'was not') + ' preserved');
});
channel.on(:attached) do |channel_state_change|
  puts "channel #{channel.name} is now attached"
  puts "Message continuity #{channel_state_change.resumed ? 'was' : 'was not'} preserved"
end
channel.on(ChannelEvent.attached, new ChannelStateListener() {
  @Override
  public void onChannelStateChanged(ChannelStateChange stateChange) {
    System.out.println("channel " + channel.name + " is now attached");
    if (stateChange.resumed) {
      System.out.println("Message continuity was preserved");
    } else {
      System.out.println("Message continuity was not preserved");
    }
  }
});
var channel = realtime.Channels.Get("chatroom");
channel.On(ChannelEvent.Attached, stateChange => {
  Console.WriteLine("channel " + channel.Name + " is now attached");
  if (stateChange.resumed) {
    Console.WriteLine("Message continuity was preserved");
  } else {
    Console.WriteLine("Message continuity was not preserved");
  }
});
[channel on:ARTChannelEventAttached call:^(ARTChannelStateChange *stateChange) {
  NSLog(@"channel %@ is now attached", channel.name);
  if (stateChange.resumed) {
    NSLog(@"Message continuity was preserved");
  } else {
    NSLog(@"Message continuity was not preserved");
  }
}];
channel.on(.Attached) { stateChange in
  print("channel \(channel.name) is now attached")
  if (stateChange.resumed) {
    print("Message continuity was preserved")
  } else {
    print("Message continuity was not preserved")
  }
}

Alternatively a listener may be registered so that it receives all state change events.

var myListener = function(stateChange) {
  console.log('channel state is ' + stateChange.current);
  console.log('previous state was ' + stateChange.previous);
  if(stateChange.reason) {
    console.log('the reason for the state change was: ' + stateChange.reason.toString());
  }
});
channel.on(myListener);
var myListener = function(stateChange) {
  console.log('channel state is ' + stateChange.current);
  console.log('previous state was ' + stateChange.previous);
  if(stateChange.reason) {
    console.log('the reason for the state change was: ' + stateChange.reason.toString());
  }
});
channel.on(myListener);
channel.on do |channel_state_change|
  puts "channel state is #{channel_state_change.current}"
end
channel.on(new ChannelStateListener() {
  @Override
  public void onChannelStateChanged(ChannelStateChange stateChange, ErrorInfo reason) {
    System.out.println("channel state is " + ChannelState.values()[stateChange.current]);
  }
});
channel.On(stateChange => Console.WriteLine("channel state is " + stateChange.Current));
ARTEventListener *listener = [channel on:^(ARTChannelStateChange *stateChange) {
    NSLog(@"channel state is %@", stateChange.current);
}];
let listener = channel.on { stateChange in
    print("channel state is \(stateChange.current)")
}

Previously registered listeners can be removed individually or all together.

/* remove the listener registered for a single event */
channel.off('attached', myListener);

/* remove the listener registered for all events */
channel.off(myListener);
/* remove the listener registered for a single event */
channel.off('attached', myListener);

/* remove the listener registered for all events */
channel.off(myListener);
# remove the listener proc registered for a single event
channel.off(:attached, &my_proc)

# remove the listener proc registered for all events
channel.off(&my_proc)
/* remove the listener registered for a single event */
channel.off(ChannelEvent.attached, channelStateListener);

/* remove the listener registered for all events */
channel.off(channelStateListener);
// remove the listener registered for a single event
channel.Off(ChannelEvent.Attached, channelStateListener);

// remove the listener registered for all events
channel.Off(channelStateListener);
// remove the listener registered for a single event
[channel off:ARTChannelEventAttached listener:listener];

// remove the listener registered for all events
[channel off:listener];
// remove the listener registered for a single event
channel.off(.Attached, listener: listener)

// remove the listener registered for all events
channel.off(listener)

Handling channel failures

Channel attach and detach operations are asynchronous – after initiating an attach request, the client will wait for a response from Ably that confirms that the channel is established on the service and then trigger a state change event.

The client libraries will attempt to automatically recover from non-fatal error conditions. However, you can handle them yourself if you prefer by subscribing to channel state changes, or using the callbacks availablewaiting for a result when explicitly calling attach.

realtime.channels.get('private:chatroom').attach(function(err) {
  if (err) {
    console.error('Attach failed: ' + err);
  }
});
realtime.channels.get('private:chatroom').attach(function(err) {
  if (err) {
    console.error('Attach failed: ' + err);
  }
});
deferrable = realtime.channels.get('private:chatroom').attach
deferrable.errback do |error|
  puts "Attach failed: #{error}"
end
Channel channel = realtime.channels.get("private:chatroom");
channel.on(new ChannelStateListener() {
  @Override
  public void onChannelStateChanged(ChannelStateChange stateChange, ErrorInfo reason) {
    switch (stateChange.current) {
      case failed: {
        System.out.println("Attach failed: " + reason.message);
      }
    }
  }
});
channel.attach();
var privateChannel = realtime.Channels.Get("private:chatroom");
privateChannel.Attach((_, error) => {
    if (error != null)
    {
        Console.WriteLine("Attach failed: " + error.message);
    }
});
[[realtime.channels get:@"private:chatroom"] attach:^(ARTErrorInfo *error) {
    if (error) {
        NSLog(@"Attach failed: %@", error);
    }
}];
realtime.channels.get("private:chatroom").attach { error in
    if let error = error {
        print("Attach failed: \(error)")
    }
}

Fatal channel errors

Some classes of errors are fatal. These cause the channel to move to the FAILED state. The client library will not attempt any automatic recovery actions. For example: attempting to attach to a channel that the token you’re using does not have the subscribe capability for will cause that channel to enter the FAILED state.

Note that while fatal errors won’t get better on their own, they can be fixable. For example, if a channel goes into the FAILED state due to the client not having the right capabilities to attach to it, that client could use Auth#authorize() to obtain a new token which does have the right capabilities, then call attach() on the channel. While the library will not automatically reattach in the FAILED state, explicit calls to attach() will make the client try again.

Nonfatal errors

Other types of errors are nonfatal. For example, a client may have network connectivity issues, or a channel may experience a loss of strict message continuity. The library will automatically attempt to recover from these events. If channel continuity is lost in the process, the library will notify you though a resumed flag in the ATTACHED or UPDATE event, so you can decide how to handle that failure.

For every channel ATTACHED and UPDATE event, the ChannelStateChange object contains a resumed attribute. When true, there has been no loss of continuity from the last time the channel was attached. When false, there has been a loss of continuity. So for example:

  • The first time you attach to a channel on a fresh connection, resumed will be false, as there was nothing to continue from.
  • If you successfully recover a connection and reattach to your channels, the resumed flag on the ATTACHED events will tell you whether messages continuity was preserved. Any channel for which it’s true is guaranteed to receive every message it missed while the client was disconnected.
  • If you resume or recover a connection unsuccessfully (so you get a fresh connection) — generally because you were disconnected for more than two minutes, which is how long Ably holds connection state for — continuity is lost. If you were resuming, all your channels (which will have gone into the SUSPENDED state after two minutes) will still reattach automatically, and you will get ATTACHED events with resumed false.
  • If Ably needs to signal a loss of message continuity on an attached channel (for example, during a partially successful resume where the client was disconnected for less than two minutes), you will get an UPDATE event with resumed false.

Connection state change side effects on channels

  • If the connection state becomes CLOSED, all channels will become DETACHED
  • If the connection state becomes FAILED, all channels will become FAILED
  • If the connection state becomes SUSPENDED, all previously-ATTACHED or ATTACHING channels will become SUSPENDED
  • If the connection state becomes CONNECTED, any channels that were SUSPENDED will be automatically reattached

Channel namespaces

One or more channel namespaces, or channel name prefixes, may be configured for an app in your dashboard. When a channel is created whose name is prefixed with one of the namespaces, the channel assumes certain configured attributes associated with that namespace. For example, a channel namespace named “private” would match channels named “private”, “private:chat”, “private:chat:mike”.

Namespace-prefixed channel names are delimited by a single colon :; the first component of the channel name (from the start up to and including the last character before the colon) is the namespace. A channel name may validly contain a colon even if the namespace component does not correspond to a namespace; also, a channel may contain multiple colons and only the component up to the first colon will be matched with a namespace. The only restriction on channel names is that a channel name may not start with a colon :, an open square bracket [ and it may not be empty.

Namespaces are defined and configured via the application dashboard settings. The namespace attributes that can be configured are:

  • Persisted messages – If enabled, all messages within this namespace will be stored according to the storage rules for your account. You can access stored messages via the history API
  • Require identification – if enabled, clients will not be permitted to subscribe to matching channels unless they are both authenticated and identified (they have an assigned client ID). Anonymous clients are not permitted to join these channels. Find out more about authenticated and identified clients
  • Require TLS – if enabled, only clients who have connected to Ably over TLS will be allowed to join the channel

Key or token capabilities can also specify access rights based on channel namespace, find out more about authentication

Messages

Each message published has an optional event name propertymemberattribute and a data propertymemberattribute carrying the payload of the message. Various primitive and object types are defined, portable and supported in all clients, enabling clients to be interoperable despite being hosted in different languages or environments.

The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and Null objects. Client libraries detect the supplied message payload and encode the message appropriately.

Subscribing to messages

The name propertymemberattribute of published messages does not affect the distribution of a channel message to clients but may be used as a (purely client-side) subscription filter, allowing a client to register a listener that only sees a subset of the messages received on the channel. When subscribing, a message listener can subscribe to see all messages on the channel or only a subset whose name matches a given name string.

The client can choose whether or not to receive messages that they themselves publish using ClientOptions#echoMessagesClientOptions#echo_messages.

A client can subscribe to all messages on a channel by passing a listener function to the subscribe method. The listener is passed a Message object for each message received.


A client can register for messages on a channel by implementing MessageListener and calling the subscribe(MessageListener listener) or subscribe(String name, MessageListener listener) method. The listener is passed an array of one or more Message objects when messages are received.


A client can subscribe to all messages on a channel by passing a block to the subscribe method. The block is passed a Message object for each message are received.


A client can subscribe to all messages on a channel by passing a lambda expression to the Subscribe method. The lambda is passed a Message object for each message are received.
channel.subscribe(function(message) {
  console.log('message received for event ' + message.name);
  console.log('message data:' + message.data);
});
channel.subscribe(function(message) {
  console.log('message received for event ' + message.name);
  console.log('message data:' + message.data);
});
channel.subscribe(new MessageListener() {
  @Override
  public void onMessage(Message message) {
    System.out.println("Message received: " + message.data);
  }
});
channel.Subscribe(message =>
{
    Console.WriteLine($"message received for event {message.name}");
    Console.WriteLine($"message data: {message.data}");
});
channel.subscribe do |message|
  puts "message received for event #{message.name}"
  puts "message data: #{message.data}"
end
[channel subscribe:^(ARTMessage *message) {
    NSLog(@"message received for event %@", message.name);
    NSLog(@"message data: %@", message.data);
}];
channel.subscribe { message in
    print("message received for event \(message.name)")
    print("message data: \(message.data)")
}

Alternatively a listener may be registered so that it is called only for messages having a specific event name.

channel.subscribe('myEvent', function(message) {
  console.log('message received for event ' + message.name);
  console.log('message data:' + message.data);
});
channel.subscribe('myEvent', function(message) {
  console.log('message received for event ' + message.name);
  console.log('message data:' + message.data);
});
channel.subscribe("myEvent", new MessageListener() {
  @Override
  public void onMessage(Message message) {
    System.out.println("Message received: " + message.data);
  }
});
channel.Subscribe("myEvent", message =>
{
    Console.WriteLine($"message received for event {message.name}");
    Console.WriteLine($"message data: {message.data}");
});
channel.subscribe('myEvent') do |message|
  puts "message received for event #{message.name}"
  puts "message data: #{message.data}"
end
channel.subscribe("myEvent") { message in
    print("message received for event \(message.name)")
    print("message data: \(message.data)")
}
[channel subscribe:@"myEvent" callback:^(ARTMessage *message) {
    NSLog(@"message received for event %@", message.name);
    NSLog(@"message data: %@", message.data);
}];

Previously registered listeners can be removed individually or all together.

/* remove the listener registered for a single event */
channel.unsubscribe('myEvent', myListener);

/* remove the listener registered for all events */
channel.unsubscribe(myListener);
/* remove the listener registered for a single event */
channel.unsubscribe('myEvent', myListener);

/* remove the listener registered for all events */
channel.unsubscribe(myListener);
/* remove a single listener */
channel.unsubscribe(myListener);

/* remove the listener registered for all events */
channel.unsubscribe("myEvent", myListener);
/* remove a single listener */
channel.Unsubscribe(myHandler);

/* remove the listener registered for all events */
channel.Unsubscribe("myEvent", myHandler);
# remove the listener proc registered for a single event
channel.unsubscribe("myEvent", &my_proc)

# remove the listener proc registered for all events
channel.unsubscribe(&my_proc)
// remove the listener registered for a single event
[channel unsubscribe:@"myEvent" listener:listener];

// remove the listener registered for all events
[channel unsubscribe:listener];
// remove the listener registered for a single event
channel.unsubscribe("myEvent", listener: listener)

// remove the listener registered for all events
channel.unsubscribe(listener)

Publishing messages

Channels expose a publishPublish method whereby a client can publish either a single message or an array of messages to a channel. A listener optionally passed in to the publishPublish method enables the client to know whether or not the operation succeeded.

channel.publish('event', 'This is my payload', function(err) {
  if(err) {
    console.log('Unable to publish message; err = ' + err.message);
  } else {
    console.log('Message successfully sent');
  }
});
channel.publish('event', 'This is my payload', function(err) {
  if(err) {
    console.log('Unable to publish message; err = ' + err.message);
  } else {
    console.log('Message successfully sent');
  }
});
deferrable = channel.publish('event', 'This is my payload') do
  puts 'Messages successfully sent'
end
deferrable.errback do |err|
  puts "Unable to publish messages; err = #{err}"
end
channel.publish("event", "This is my payload", new CompletionListener() {
  @Override
  public void onError(ErrorInfo reason) {
    System.out.println("Unable to publish message; err = " + reason.message);
  }
  @Override
  public void onSuccess() {
    System.out.println("Message successfully sent");
  }
});
channel.Publish("event", "payload", (success, error) =>
{
  if (error != null) {
    Console.WriteLine("Unable to publish message. Reason: " + error.message);
  } else {
    Console.WriteLine("Message published successfully");
  }
});
[channel publish:@"event" data:@"This is my payload" callback:^(ARTErrorInfo *error) {
  if (error) {
    NSLog(@"Unable to publish message; err = %@", error.message);
  } else {
    NSLog(@"Message successfully sent");
  }
}];
channel.publish("event", data: "This is my payload") { error in
  if let error = error {
    print("Unable to publish message; err = \(error.message)")
  } else {
    print("Message successfully sent")
  }
}

Channels also expose an async version PublishAsync of the Publish call which resumes execution once the message is confirmed received. It is purely for convenience.

var result = await channel.PublishAsync("event", "payload");
if(result.IsFailure) {
  Console.WriteLine("Unable to publish message. Reason: " + result.Error.message);
} else {
  Console.WriteLine("Message published successfully");
}

Retrieving message history

Channels expose a historyHistory method providing a means for clients to obtain messages previously sent on the channel. Channel history can be used to return continuous message history up to the exact point a realtime channel was attached.

History provides access to instantaneous “live” history as well as the longer term persisted history for attached channels. If persisted history is enabled for the channel, then messages will typically be stored for 24 – 72 hours. If persisted history is not enabled, Ably retains the last two minutes of message history in memory.

The following example retrieves the first two pages of historical messages published up until the point the channel was attached.

channel.attach(function() {
  channel.history({ untilAttach: true }, function(err, resultPage) {
    if(err) {
      console.log('Unable to get channel history; err = ' + err.message);
    } else {
      console.log(resultPage.items.length + ' messages received in first page');
      if(resultPage.hasNext()) {
        resultPage.next(function(err, nextPage) { ... });
      }
    }
  });
});
channel.attach(function() {
  channel.history({ untilAttach: true }, function(err, resultPage) {
    if(err) {
      console.log('Unable to get channel history; err = ' + err.message);
    } else {
      console.log(resultPage.items.length + ' messages received in first page');
      if(resultPage.hasNext()) {
        resultPage.next(function(err, nextPage) { ... });
      }
    }
  });
});
Param[] options = new Param[]{ new Param("untilAttach", "true") };
PaginatedResult<Message> resultPage = channel.history(options);
System.out.println(resultPage.items().length + " messages received in first page");
if(resultPage.hasNext()) {
  PaginatedResult<Message> nextPage = resultPage.next();
  System.out.println(nextPage.items().length + " messages received in second page");
}
var history = await channel.HistoryAsync(untilAttach: true);
Console.WriteLine($"{history.Items.Count} messages received in the first page");
if (history.HasNext)
{
  var nextPage = await history.NextAsync();
  Console.WriteLine($"{nextPage.Items.Count} messages received in the second page");
}
channel.attach do
  channel.history(until_attach: true) do |result_page|
    puts "#{result_page.items.length} messages received in first page"
    if result_page.has_next?
      result_page.next { |next_page| ... }
    end
  end
end
[channel attach:^(ARTErrorInfo *error) {
    ARTRealtimeHistoryQuery *query = [[ARTRealtimeHistoryQuery alloc] init];
    query.untilAttach = true;
    [channel history:query callback:^(ARTPaginatedResult<ARTMessage *> *resultPage, ARTErrorInfo *error) {
        NSLog(@"%lu messages received in first page", (unsigned long)[resultPage.items count]);
        if (resultPage.hasNext) {
            [resultPage next:^(ARTPaginatedResult<ARTMessage *> *nextPage, ARTErrorInfo *error) {
                // ...
            }];
        }
    } error:nil];
}];
channel.attach { error in
    let query = ARTRealtimeHistoryQuery()
    query.untilAttach = true
    try! channel.history(query) { resultPage, error in
        let resultPage = resultPage!
        print("\(resultPage.items.count) messages received in first page")
        if resultPage.hasNext {
            resultPage.next { nextPage, error in
                // ...
            }
        }
    }
}

See the history documentation for further details of the supported query parameters.

Presence

Channels expose a presencePresence member which a client can use to obtain channel presence information and to enter and leave the presence channel itself. See the presence documentation for details.

Channel API Reference

Channel PropertiesARTRealtimeChannel PropertiesAbly::Realtime::Channel Attributesio.ably.lib.realtime.Channel MembersIO.Ably.Realtime.RealtimeChannel Properties

The Channel object exposes the following public propertiesattributesmembers:

stateState

The current io.ably.lib.realtime.ChannelState stateIO.Ably.Realtime.ChannelState stateAbly::Realtime::Channel::STATE stateARTRealtimeChannelStateChannelState of this Channel. See the supported channel states for more information.

errorReasonreasonerror_reasonErrorReason

When a channel failure occurs this attributememberpropertyproperty is populated.
The type is ErrorInfoAblyException.

nameName

The name String unique to this channel.

presencePresence

Provides access to the Presence object for this channel which can be used to access members present on the channel, or participate in presence.

Methods

publishPublish

There are two overloaded versions of this method:

publish(String name, Object data, callback(ErrorInfo err))Deferrable publish(String name, Object data) → yieldsvoid publish(String name, Object data, CompletionListener listener)void Publish(string name, object data, Action<bool, ErrorInfo> callback = null, string clientId = null)publish(name: String?, data: AnyObject?, callback: ((ARTErrorInfo?) → Void)?)

Publish a single message on this channel based on a given event name and payload. A callbacklistener may optionally be passed in to this call to be notified of success or failure of the operation. If the channel is initialized (i.e. no attempt to attach has yet been made for this channel), then calling publish will implicitly attach the channel.

publish(Object[] messages, callback(ErrorInfo err))Deferrable publish(Message[] messages) → yieldsvoid publish(Message[] messages, CompletionListener listener)void Publish(IEnumerable<Message> messages, Action<bool, ErrorInfo> callback = null)publish(messages: [ ARTMessage ], callback: ((ARTErrorInfo?) → Void)?)

Publish several messages on this channel. A callbacklistenerblock may optionally be passed in to this call to be notified of success or failure of the operation. If the channel is initialized (i.e. no attempt to attach has yet been made for this channel), then calling publish will implicitly attach the channel.

Parameters

name
event name for the published message
Type: String
data
data payload for the message. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and null.
Type: Object
data
data payload for the message. The supported payload types are Strings, JsonObject, binary data as byte arrays, and null.
Type: Object
data
data payload for the message. The supported payload types are Strings, binary data as byte arrays, any plain c# class that can be serialized to Json, and null.
Type: Object
data
data payload for the message. The supported payload types are Strings, Hash or Array objects that can be serialized to JSON using to_json, binary data as ASCII-8BIT byte arrays, and null.
Type: Object
data
data payload for the message. The supported payload types are NSString, NSDictionary or NSArray objects that can be serialized to JSON, binary data as NSData, and nil.
Type: Object
messages
An array of message objects to publish
Type: Message []
callback
is a function of the form function(err) which is called upon completion
listener
Listener to be notified on completion
Type: CompletionListener
callback
is an action of the form Action<bool, ErrorInfo> which is called upon completion
&block
yields upon successfully publishing the message
callback
called upon publishing the message, or with an error

Callback result

On successful publish of the message, err is null. On failure to publish the message, err contains an ErrorInfo object describing the failure reason.

Callback result

On successful publish of the message, error is null. On failure to publish the message, error contains an ErrorInfo object describing the failure reason.

Listener result

On successful publish of the message, the onSuccess method of the CompletionListener is called. On failure to publish the message, the onError method is called with an ErrorInfo argument describing the failure reason.

Returns

A Deferrable object is returned from the method.

On successful publish of the message, the registered success blocks for the Deferrable and any block provided to the method are executed. On failure to publish the message, the errback callbacks of the Deferrable are called with an ErrorInfo argument describing the failure reason.

subscribeSubscribe

There are overloaded versions of this method:

subscribe(listener(Message))void subscribe(MessageListener listener)void Subscribe(Action<Message> handler)subscribe → yields Messagesubscribe(callback: (ARTMessage) → Void) → ARTEventListener?

Subscribe to messages on this channel. The caller supplies a listener functiona lambda expressionan implementation of the MessageListener interfacea block, which is called each time one or more messages arrives on the channel.

subscribe(String name, listener(Message))void subscribe(String name, MessageListener listener)void Subscribe(string name, Action<Message> handler)subscribe(String name) → yields Messagesubscribe(name: String, callback: (ARTMessage) → Void) → ARTEventListener?

Subscribe to messages with a given event name on this channel. The caller supplies a listener functiona lambda expressionan implementation of the MessageListener interfacea block, which is called each time one or more matching messages arrives on the channel.

subscribe(String[] names, listener(Message))void subscribe(String[] names, MessageListener listener)subscribe(String *names) → yields Message

Subscribe a single listener to messages on this channel for multiple event name values.

Parameters

name
The event name to subscribe to
Type: String
names
An argument array of event names to subscribe to
Type: String[] *argument
listener
is a function of the form function(message) to be called for each message
MessageListener listener
Message listener to be notified for matching messages
&block
yields each matching message when received on the channel
callback
called with each matching message when received on the channel
handler
called with each matching message when received on the channel

Considerations

  • If the channel is initialized (i.e. no attempt to attach has yet been made for this channel), then calling subscribe will implicitly attach the channel. However, regardless of the implicit attach outcome, the listenerblockhandler will still be registered
  • If subscribe is called more than once with the same listenerblockhandler, then duplicates will be registered. For example, if you subscribe twice with the same listenerblockhandler and a message is later received, the same listenerblockhandler will be invoked twice
  • The registered listenerblockhandler remains active on the channel regardless of the current channel state. For example, if you call subscribe when a channel is attached and it later becomes detached or even failed, when the channel is reattached and a message is received, the listenersblockshandlers originally registered will still be invoked. Listeners are only removed when calling unsubscribe or when a channel is released using the Realtime.channels.release(name)Realtime.Channels.Release(name) method
unsubscribeUnsubscribe

There are sixthree overloaded versions of this method:

unsubscribe(String name, listener)void unsubscribe(String name, MessageListener listener)bool Unsubscribe(string eventName, Action<Message> handler)unsubscribe(String name, &listener_proc)unsubscribe(name: String, listener: ARTEventListener)

Unsubscribe the given listener for the specified event name. This removes an earlier event-specific subscription.

unsubscribe(listener)void unsubscribe(MessageListener listener)bool Unsubscribe(Action<Message> handler)unsubscribe(&listener_proc)unsubscribe(listener: ARTEventListener)

Unsubscribe the given listener (for any/all event names). This removes an earlier subscription.

unsubscribe(String[] names, listener)

Unsubscribe the given listener from all event names in the array.

unsubscribe(String name)

Unsubscribe all listeners for a given event name.

unsubscribe(String[] names)

Unsubscribe all listeners for all event names in the array.

unsubscribe()void unsubscribe()void Unsubscribe()unsubscribe()

Unsubscribes all listeners to messages on this channel. This removes all earlier subscriptions.

Parameters

name
The event name to unsubscribe from
Type: String
names
An array of event names to unsubscribe from
Type: String[]
listener
is the callback listener function that was previously subscribed
listener
previously registered listener
Type: MessageListener
&listener_block
previously registered listener block
listener
previous return value from a subscribe call
handler
is the lambda expression that was previously subscribed
historyHistory

history(Object options, callback(ErrorInfo err, PaginatedResult<Message> resultPage))Deferrable history(Hash options) → yields PaginatedResult<Message>PaginatedResult<Message> history(Param [] options)Task<PaginatedResult> HistoryAsync(HistoryRequestParams dataQuery, bool untilAttach = false)history(query: ARTRealtimeHistoryQuery?, callback: (ARTPaginatedResult<ARTMessage>?, ARTErrorInfo?) → Void) throws

Gets a paginated set of historical messages for this channel. If the channel is configured to persist messages to disk, then message history will typically be available for 24 – 72 hours. If not, messages are only retained in memory by the Ably service for two minutes.

Parameters

optionsquerydataQuery
an optional object containing the query parametersan optional set of key value pairs containing the query parameters, as specified in the message history API documentation.
Type: ObjectARTRealtimeHistoryQueryHistoryRequestParamsHashParam []
callback
is a function of the form: function(err, resultPage)
&block
yields a PaginatedResult<Message> object
callback
called with a ARTPaginatedResult<ARTMessage> object or an error

Further details of the supported options params, see message history API documentation.

Callback result

On success, resultPage contains a PaginatedResult encapsulating an array of Message objects corresponding to the current page of results. PaginatedResult supports pagination using next() and first() methods.

On failure to retrieve message history, err contains an ErrorInfo object with the failure reason.

Returns

On success, the returned PaginatedResult encapsulates an array of Message objects corresponding to the current page of results. PaginatedResult supports pagination using next and first methods.

Failure to retrieve the message history will raise an AblyException

Returns

The return value is Task<PaginatedResult<Message>> which needs to be awaited.

On success, the returned PaginatedResult encapsulates an array of Message objects corresponding to the current page of results. PaginatedResult supports pagination using NextAsync and FirstAsync methods.

Failure to retrieve the message history will raise an AblyException

Returns

A Deferrable object is returned from the method.

On success, the registered success blocks for the Deferrable and any block provided to the method yield a PaginatedResult that encapsulates an array of Message objects corresponding to the current page of results. PaginatedResult supports pagination using next() and first() methods.

Failure to retrieve the message history will trigger the errback callbacks of the Deferrable with an ErrorInfo object with the failure reason.

attachAttach

attach(callback(ErrorInfo err))void attach()void Attach(Action<TimeSpan, ErrorInfo?> callback = null)Deferrable attach → yieldsattach(callback: ((ARTErrorInfo?) → Void)?)

Attach to this channel ensuring the channel is created in the Ably system and all messages published on the channel will be received by any channel listeners registered using subscribe()Subscribe()subscribe. Any resulting channel state change will be emitted to any listeners registered using the onOn or onceOnce methods.

As a convenience, attach()Attach()attach will be called implicitly if either publish()Publish()publish or subscribe()Subscribe()subscribe for the Channel is called, or enter()Enter()enter or subscribe()Subscribe()subscribe is called on the Presence for this Channel.

Parameters

callback
is a function of the form function(err) and is called once the channel attach succeeds or fails
&block
yields once the channel becomes attached
callback
is a lambda expression of the form Action<TimeSpan, ErrorInfo> and is called once the channel attach succeeds or fails
callback
called once the channel becomes attached or if an error occurs

Returns

A Deferrable object is returned from the attach method.

On successful attachment, the success callbacks for the Deferrable are called and any block provided to the method is yielded. Failure to attach will trigger the errback callbacks of the Deferrable with an ErrorInfo object with the failure reason.

detachDetach

detach(callback(ErrorInfo err))void detach()void Detach(Action<TimeSpan, ErrorInfo> callback = null)Deferrable detach → yieldsdetach(callback: ((ARTErrorInfo?) → Void)?)

Detach from this channel. Any resulting channel state change will be emitted to any listeners registered using the onOn or onceOnce methods.

Please note: Once all clients globally have detached from the channel, the channel will be released in the Ably service within two minutes.

Parameters

callback
is a function of the form function(err) and is called once the channel detach succeeds or fails
callback
is a lambda expression in the form Action<TimeSpan, ErrorInfo> and is called once the channel detach succeeds or fails
&block
yields once the channel becomes detached
callback
called once the channel becomes detached or if an error occurs

Returns

A Deferrable object is returned from the detach method.

On successful detachment, the registered success blocks for the Deferrable and any block provided to the method are executed. Failure to detach will trigger the errback callbacks of the Deferrable with an ErrorInfo object with the failure reason.

onOn

There are threetwo overloaded versions of this method:

on(String event, listener(ChannelStateChange stateChange))on(ChannelEvent *event) → yields ChannelStateChangevoid on(ChannelEvent event, ChannelStateListener listener)void On(ChannelEvent event, Action<ChannelStateChange> action)on(event: ARTChannelEvent, call: (ARTChannelStateChange?) → Void) → ARTEventListener

Register the given listener blockfunction for the specified ChannelEvent on the Channel.
The listener is passed a ChannelStateChangeARTChannelStateChange object that contains the current state, previous state, a boolean indicating whether the channel was resumed, and an optional reason for the state change.

on(String[] events, listener(ChannelStateChange stateChange))

Same as above, but registers multiple listeners, one for each event in the array.

on(listener(ChannelStateChange stateChange))on → yields ChannelStateChangevoid On(Action<ChannelStateChange> listener)void on(ChannelStateListener listener)on(call: (ARTChannelStateChange?) → Void) → ARTEventListener

Register the given listener blockfunctionlambda expression for all ChannelEvents on the Channel.
The listener is passed a ChannelStateChangeARTChannelStateChange object that contains the current state, previous state, the event, a boolean indicating whether the channel was resumed, and an optional reason for the state change.

Parameters

event(s)
the channel event(s) to subscribe to, see ChannelEvent for supported channel events
Type: String or String[]
event
the channel event to subscribe to
Type: ChannelEvent
event
the channel event to subscribe to
Type: ChannelEvent
event
the channel event as a Symbol such as :attached or a ChannelEvent object to subscribe to
Type: ChannelEvent
event
the ARTChannelEvent to subscribe to
Type: ARTChannelEvent
listener
is a function of the form function(stateChange) to be notified for matching event changes.
listener
listener to be notified for matching event changes
Type: ChannelStateListener
action
lambda expression to be notified for matching event changes
Type: ChannelStateChange
&block
listener block that is yielded to for matching event changes
call
called possibly with an ErrorInfo

Example

Browser ChannelState change example

onceOnce

There are two overloaded versions of this method:

once(String event, listener(ChannelStateChange stateChange))once(ChannelEvent *event) → yields ChannelStateChangevoid once(ChannelEvent event, ChannelStateListener listener)void Once(ChannelEvent event, Action<ChannelStateChange> action)once(event: ARTChannelEvent, call: (ARTChannelStateChange?) → Void) → ARTEventListener

Register the given listener blockfunctionlambda expression for a single occurrence of the specified ChannelEvent on the Channel. Once the listener has been called, it is removed as a registered listener and will not be called again.
The listener is passed a ChannelStateChangeARTChannelStateChange object that contains the current state, previous state, the event, a boolean indicating whether the channel was resumed, and an optional reason for the event change.

once(listener(ChannelStateChange stateChange))once → yields ChannelStateChangevoid once(ChannelStateListener listener)void Once(Action<ChannelStateChange> listener)once(call: (ARTChannelStateChange?) → Void) → ARTEventListener

Register the given listener blockfunctionlambda expression for a single occurrence of any ChannelEvent on the Channel. Once the listener has been called, it is removed as a registered listener and will not be called again.
The listener is passed a ChannelStateChangeARTChannelStateChange object that contains the current state, previous state, the event, a boolean indicating whether the channel was resumed, and an optional reason for the event change.

Parameters

event
the channel event to subscribe to, see ChannelEvent for supported channel events
Type: String
event
the channel event to subscribe to
Type: ChannelEvent
event
the channel event to subscribe to
Type: ChannelEvent
event
the channel event as a Symbol such as :attached or a ChannelEvent object to subscribe to
Type: ChannelEvent
event
the ARTChannelEvent to subscribe to
Type: ARTChannelEvent
listener
is a function of the form function() to be notified for a single occurrence of a matching event change. The current event is available as this.event
listener
listener to be notified for a single occurrence of a matching event change
Type: ChannelStateListener
&block
listener block that is yielded to for a single occurrence of a matching event change
listener
listener lambda expression that is notified only once for a matching event change
call
called possibly with an ErrorInfo
offOff

There are sixtwo overloaded versions of this method:

off(String event, listener)off(ChannelEvent *event, &block)void off(ChannelEvent event, ChannelStateListener listener)void Off(ChannelEvent event, Action<ChannelStateChange> listener)off(event: ARTChannelEvent, listener: ARTEventListener)

Remove the given listener block for the ChannelEvent .

off(listener)off(&block)void off(ChannelStateListener listener)void Off(Action<ChannelStateChange> listener)off(listener: ARTEventListener)

Remove the given listener block for all ChannelEvents.

off(String[] events, listener)

Removes the given listener from all ChannelEvents in the array.

off(String event)

Removes all listeners for a given ChannelEvent .

off(String[] events)

Removes all listeners for all ChannelEvents in the array.

off()

Removes all listeners (including both those registered against specific events and those registered without an event).

Parameters

event(s)
the channel event(s) to unsubscribe from
Type: String or String[]
event
the channel event to unsubscribe from
__Type: ChannelEvent-
event
the channel event to unsubscribe from
Type: ChannelEvent
event
the channel event as a Symbol such as :detached or a ChannelEvent object to unsubscribe from
Type: ChannelEvent
event
the ARTChannelEvent to unsubscribe from
Type: ARTChannelEvent
listener
is the listener function to be removed
listener
is the listener to be removed
Type: @ChannelStateListener
listener
is the listener function to be removed
&block
is the listener block to be removed
listener
previous return value from a on or once call

ChannelStateARTRealtimeChannelStateChannel::STATE Enumio.ably.lib.realtime.ChannelState EnumIO.Ably.Realtime.ChannelState Enum

ChannelState is a String with a value matching any of the Realtime Channel states.

var ChannelStates = [
  'initialized',
  'attaching',
  'attached',
  'detaching',
  'detached',
  'failed',
  'suspended'
]

io.ably.lib.realtime.ChannelState is an enum representing all the Realtime Channel states.

public enum ChannelState {
  initialized,  // 0
  attaching,    // 1
  attached,     // 2
  detaching,    // 3
  detached,     // 4
  failed        // 5
}

IO.Ably.Realtime.ChannelState is an enum representing all the Realtime Channel states.

public enum ChannelState
{
    Initialized = 0,
    Attaching = 1,
    Attached = 2,
    Detaching= 3,
    Detached = 4,
    Failed = 5
};

Ably::Realtime::Channel::STATE is an enum-like value representing all the Realtime Channel states. STATE can be represented interchangeably as either symbols or constants.

Symbol states

:initialized # => 0
:attaching # =>   1
:attached # =>    2
:detaching # =>   3
:detached # =>    4
:failed # =>      5

Constant states

Channel::STATE.Initialized # => 0
Channel::STATE.Attaching # =>   1
Channel::STATE.Attached # =>    2
Channel::STATE.Detaching # =>   3
Channel::STATE.Detached # =>    4
Channel::STATE.Failed # =>      5

Example usage

# Example with symbols
channel.on(:attached) { ... }

# Example with constants
channel.on(Ably::Realtime::Channel::STATE.Attached) { ... }

# Interchangeable
Ably::Realtime::Channel::STATE.Attached == :attached # => true

ARTRealtimeChannelState is an enum representing all the Realtime Channel states.

typedef NS_ENUM(NSUInteger, ARTRealtimeChannelState) {
    ARTRealtimeChannelInitialized,
    ARTRealtimeChannelAttaching,
    ARTRealtimeChannelAttached,
    ARTRealtimeChannelDetaching,
    ARTRealtimeChannelDetached,
    ARTRealtimeChannelFailed
};
public enum ARTRealtimeChannelState : UInt {
    case Initialized
    case Attaching
    case Attached
    case Detaching
    case Detached
    case Failed
}

ChannelEventARTChannelEventChannel::EVENT Enumio.ably.lib.realtime.ChannelEvent EnumIO.Ably.Realtime.ChannelEvent Enum

ChannelEvent is a String that can be emitted as an event on the Channel object; either a ChannelState or an update event.

var ChannelEvents = [
  'initialized',
  'attaching',
  'attached',
  'detaching',
  'detached',
  'failed',
  'suspended',
  'update'
]

io.ably.lib.realtime.ChannelEvent is an enum representing all the events that can be emitted be the Channel; either a ChannelState or an update event.

public enum ChannelEvent {
  initialized,  // 0
  attaching,    // 1
  attached,     // 2
  detaching,    // 3
  detached,     // 4
  failed        // 5
  update        // 6
}

IO.Ably.Realtime.ChannelEvent is an enum representing all the events that can be emitted be the Channel; either a ChannelState or an Update event.

public enum ChannelEvent
{
    Initialized = 0,
    Attaching = 1,
    Attached = 2,
    Detaching= 3,
    Detached = 4,
    Failed = 5,
    Update = 6
};

Ably::Realtime::Channel::EVENT is an enum-like value representing all the events that can be emitted be the Channel; either a ChannelState or an :update event. EVENT can be represented interchangeably as either symbols or constants.

Symbol states

:initialized # => 0
:attaching # =>   1
:attached # =>    2
:detaching # =>   3
:detached # =>    4
:failed # =>      5
:update # =>      6

Constant states

Channel::EVENT.Initialized # => 0
Channel::EVENT.Attaching # =>   1
Channel::EVENT.Attached # =>    2
Channel::EVENT.Detaching # =>   3
Channel::EVENT.Detached # =>    4
Channel::EVENT.Failed # =>      5
Channel::EVENT.Update # =>      6

ARTChannelEvent is the enum emitted as the event in ARTRealtimeChannel.on; either a ChannelState or an Update event.

typedef NS_ENUM(NSUInteger, ARTChannelEvent) {
    ARTChannelEventInitialized,
    ARTChannelEventAttaching,
    ARTChannelEventAttached,
    ARTChannelEventDetaching,
    ARTChannelEventDetached,
    ARTChannelEventFailed,
    ARTChannelEventUpdate
};
enum ARTChannelEvent : UInt {
    case Initialized
    case Attaching
    case Attached
    case Detaching
    case Detached
    case Failed
    case Update
}

ChannelStateChangeARTRealtimeChannelStateChangeio.ably.lib.realtime.ChannelStateListener.ChannelStateChangeChannelStateChangeIO.Ably.Realtime.ChannelStateChanged

A Ably::Models::ChannelStateChangeChannelStateChangeARTRealtimeChannelStateChange is a type encapsulating state change information emitted by the Channel object. See Channel#on to register a listener for one or more events.

Attributes

currentCurrent
the new current state
Type: ChannelStateChannel::STATE@
previousPrevious
the previous state. (for the update event, this will be equal to the current state)
Type: ChannelStateChannel::STATE@
eventEvent
the event that triggered this state change
Type: ChannelEventChannel::EVENT@
reasonReason
an ErrorInfo containing any information relating to the transition
Type: ErrorInfo
resumedResumed
a boolean indicated whether message continuity on this channel is preserved, see Nonfatal channel errors for more info.
Type: Boolean

MessageARTMessageAbly::Models::Messageio.ably.lib.types.MessageIO.Ably.Message

A Message represents an individual message that is sent to or received from Ably.

PropertiesMembersAttributesAttributes

nameName
Event name, if provided
Type: String
data
The message payload, if provided
Type: String, StringBuffer, JSON Object
data
The message payload, if provided
Type: String, ByteArray, JSONObject, JSONArray
Data
The message payload, if provided
Type: String, byte[], plain C# object that can be serialized to Json
data
The message payload, if provided
Type: String, Binary (ASCII-8BIT String), Hash, Array
data
The message payload, if provided
Type: String, Bytearray, Dict, List
data
The message payload, if provided
Type: String, Binary String, Associative Array, Array
data
The message payload, if provided
Type: NSString *, NSData *, NSDictionary *, NSArray *
data
The message payload, if provided
Type: String, NSData, Dictionary, Array
idId
Unique ID assigned by Ably to this message
Type: String
clientIdclient_idClientId
The client ID of the publisher of this message
Type: String
connectionIdconnection_idConnectionId
The connection ID of the publisher of this message
Type: String
timestampTimestamp
Timestamp when the presence update was received by the Ably the realtime service, as milliseconds since the epocha Time object
Type: IntegerLong IntegerDateTimeOffsetTimeNSDate
encodingEncoding
This will typically be empty as all messages received from Ably are automatically decoded client-side using this value. However, if the message encoding cannot be processed, this attribute will contain the remaining transformations not applied to the data payload
Type: String

Message constructors

Message.fromEncoded

Message.fromEncoded(Object encodedMsg, ChannelOptions channelOptions?) → Message

A static factory method to create a Message from a deserialized Message-like object encoded using Ably’s wire protocol.

Parameters

encodedMsg
a Message-like deserialized object.
Type: Object
channelOptions
an optional ChannelOptions. If you have an encrypted channel, use this to allow the library can decrypt the data.
Type: Object

Returns

A Message object

Message.fromEncodedArray

Message.fromEncodedArray(Object[] encodedMsgs, ChannelOptions channelOptions?) → Message[]

A static factory method to create an array of Messages from an array of deserialized Message-like object encoded using Ably’s wire protocol.

Parameters

encodedMsgs
an array of Message-like deserialized objects.
Type: Array
channelOptions
an optional ChannelOptions. If you have an encrypted channel, use this to allow the library can decrypt the data.
Type: Object

Returns

An Array of Message objects

ChannelOptions ObjectARTChannelOptionsChannelOptions Hashio.ably.lib.types.ChannelOptionsIO.Ably.Rest.ChannelOptions

Currently the supported channel options are only used for configuring encryption.

ChannelOptions, a plain Javascript object, may optionally be specified when instancing a Channel, and this may be used to specify channel-specific options. The following attributes can be defined on the object:

ChannelOptions, a Hash object, may optionally be specified when instancing a Channel, and this may be used to specify channel-specific options. The following key symbol values can be added to the Hash:

ChannelOptions, an Associative Array, may optionally be specified when instancing a Channel, and this may be used to specify channel-specific options. The following named keys and values can be added to the Associated Array:

ARTio.ably.lib.types.ChannelOptions may optionally be specified when instancing a Channel, and this may be used to specify channel-specific options.

IO.Ably.ChannelOptions may optionally be specified when instancing a Channel, and this may be used to specify channel-specific options.

PropertiesMembersAttributes

cipher:cipherCipherParams
Requests encryption for this channel when not null, and specifies encryption-related parameters (such as algorithm, chaining mode, key length and key). See an example
Type: CipherParams or an options objecta Param[] listan options hashan Associative Array containing at a minimum a key

Static methods

withCipherKey

static ChannelOptions.withCipherKey(Byte[] or String key)

A helper method to generate a ChannelOptions for the simple case where you only specify a key.

Parameters

key
A binary Byte[] array or a base64-encoded String.

Returns

On success, the method returns a complete ChannelOptions object. Failure will raise an AblyException.

io.ably.lib.realtime.ChannelStateListener

A io.ably.lib.realtime.ChannelStateListener is an interface allowing a client to be notified of channel state changes for a Channel

public interface ChannelStateListener {
  // Called when the channel state changes
  public void onChannelStateChanged(ChannelStateChange stateChange, ErrorInfo reason);
}

io.ably.lib.realtime.CompletionListener

A io.ably.lib.realtime.CompletionListener is an interface allowing a client to be notified of the outcome of an asynchronous operation.

public interface CompletionListener {
  // Called when the associated operation completes successfully,
  public void onSuccess();

  // Called when the associated operation completes with an error.
  public void onError(ErrorInfo reason);
}

HistoryRequestParams

HistoryRequestParams is a type that encapsulates the parameters for a history queries. For example usage see Channel#historyChannel#History.

Members

Start
null The start of the queried interval
Type: DateTimeOffset
End
null The end of the queried interval
Type: DateTimeOffset
Limit
null By default it is null. Limits the number of items returned by history or stats
Type: Integer
Direction
Backwards Enum which is either Forwards or Backwards
Type: Direction enum
ExtraParameters
Optionally any extra query parameters that may be passed to the query. This is mainly used internally by the library to manage paging.
Type: Dictionary<string, string>

io.ably.lib.realtime.Channel.MessageListener

A io.ably.lib.realtime.Channel.MessageListener is an interface allowing a client to be notified when messages are received on a channel using a channel subscription.

public interface MessageListener {
  // Called when one or more messages are received
  public void onMessage(Message message);
}

PaginatedResultARTPaginatedResultAbly::Models::PaginatedResultio.ably.lib.types.PaginatedResultIO.Ably.PaginatedResult

A PaginatedResult is a type that represents a page of results for all message and presence history, stats and REST presence requests. The response from a Ably REST API paginated query is accompanied by metadata that indicates the relative queries available to the PaginatedResult object.

PropertiesMembersAttributes

itemsItems
contains the current page of results (for example an Array of Message or PresenceMessage objects for a channel history request)
Type: Array <Message, Presence, Stats>Type: List <Message, Presence, Stats>

Methods

firstFirst

first(callback(ErrorInfo err, PaginatedResult resultPage))PaginatedResult firstPaginatedResult first()PaginatedResult first()Task<PaginatedResult> FirstAsync()PaginatedResult first()first(callback: (ARTPaginatedResult?, ARTErrorInfo?) → Void)

Returns a new PaginatedResult for the first page of results. When using the Realtime library, the first method returns a Deferrable and yields a PaginatedResult.The method is asynchronous and returns a Task which needs to be awaited to get the PaginatedResult.

hasNextHasNexthas_next?has_next

Boolean hasNext()Boolean has_next?Boolean hasNext()Boolean has_next()Boolean HasNext()Boolean hasNext()Boolean hasNext()

Returns true if there are more pages available by calling nextNext and returns false if this page is the last page available.

isLastIsLastlast?is_last

Boolean isLast()Boolean last?Boolean isLast()Boolean is_last()Boolean IsLast()Boolean isLast()Boolean isLast()

Returns true if this page is the last page and returns false if there are more pages available by calling nextNext available.

nextNext

next(callback(ErrorInfo err, PaginatedResult resultPage))PaginatedResult nextPaginatedResult next()PaginatedResult next()Task<PaginatedResult> NextAsync()PaginatedResult next()next(callback: (ARTPaginatedResult?, ARTErrorInfo?) → Void)

Returns a new PaginatedResult loaded with the next page of results. If there are no further pages, then nulla blank PaginatedResult will be returnedNullNonenil is returned. The method is asynchronous and return a Task which needs to be awaited to get the PaginatedResultWhen using the Realtime library, the first method returns a Deferrable and yields a PaginatedResult.

Example

channel.history(function(err, paginatedResult) {
  console.log('Page 0 item 0:' + paginatedResult.items[0].data);
  paginatedResult.next(function(err, nextPage) {
    console.log('Page 1 item 1: ' + nextPage.items[1].data);
    console.log('Last page?: ' + nextPage.isLast());
  });
});
channel.history(function(err, paginatedResult) {
  console.log('Page 0 item 0:' + paginatedResult.items[0].data);
  paginatedResult.next(function(err, nextPage) {
    console.log('Page 1 item 1: ' + nextPage.items[1].data);
    console.log('Last page?: ' + nextPage.isLast());
  });
});
PaginatedResult firstPage = channel.history();
System.out.println("Page 0 item 0:" + firstPage.items[0].data);
if (firstPage.hasNext) {
  PaginatedResult nextPage = firstPage.next();
  System.out.println("Page 1 item 1:" + nextPage.items[1].data);
  System.out.println("More pages?:" + Strong.valueOf(nextPage.hasNext()));
};
PaginatedResult<Message> firstPage = await channel.HistoryAsync(null);
Message firstMessage = firstPage.Items[0];
Console.WriteLine("Page 0 item 0: " + firstMessage.data);
if (firstPage.HasNext)
{
    var nextPage = await firstPage.NextAsync();
    Console.WriteLine("Page 1 item 1:" + nextPage.Items[1].data);
    Console.WriteLine("More pages?: " + nextPage.HasNext());
}
# When using the REST sync library
first_page = channel.history
puts "Page 0 item 0: #{first_page.items[0].data}"
if first_page.has_next?
  next_page = first_page.next
  puts "Page 1 item 1: #{next_page.items[1].data}"
  puts "Last page?: #{next_page.is_last?}"
end

# When using the Realtime EventMachine library
channel.history do |first_page|
  puts "Page 0 item 0: #{first_page.items[0].data}"
  if first_page.has_next?
    first_page.next do |next_page|
      puts "Page 1 item 1: #{next_page.items[1].data}"
      puts "Last page?: #{next_page.is_last?}"
    end
  end
end
result_page = channel.history()
print 'Page 0 item 0: ' + str(result_page.items[0].data)
if result_page.has_next():
  next_page = result_page.next()
  print 'Page 1 item 1: ' + str(next_page.items[1].data)
  print 'Last page?: ' + str(next_page.is_last())
$firstPage = $channel.history();
echo("Page 0 item 0: " . $firstPage->items[0]->data);
if ($firstPage->hasNext()) {
  $nextPage = $firstPage->next();
  echo("Page 1 item 1: " . $nextPage->items[1]->data);
  echo("Last page?: " . $nextPage->isLast());
}
[channel history:^(ARTPaginatedResult<ARTMessage *> *paginatedResult, ARTErrorInfo *error) {
    NSLog(@"Page 0 item 0: %@", paginatedResult.items[0].data);
    [paginatedResult next:^(ARTPaginatedResult<ARTMessage *> *nextPage, ARTErrorInfo *error) {
        NSLog(@"Page 1 item 1: %@", nextPage.items[1].data);
        NSLog(@"Last page?: %d", nextPage.isLast());
    }];
}];
channel.history { paginatedResult, error in
    let paginatedResult = paginatedResult!
    print("Page 0 item 0: \((paginatedResult.items[0] as! ARTMessage).data)")
    paginatedResult.next { nextPage, error in
        let nextPage = nextPage!
        print("Page 0 item 0: \((nextPage.items[1] as! ARTMessage).data)")
        print("Last page? \(nextPage.isLast())")
    }
}

io.ably.lib.types.Param

Param is a type encapsulating a key/value pair. This type is used frequently in method parameters allowing key/value pairs to be used more flexible, see Channel#history for an example.

Please note that key and value attributes are always strings. If an Integer or other value type is expected, then you must coerce that type into a String.

Members

key
The key value
Type: String
value
The value associated with the key
Type: String

Get started now with our free plan

It includes 100 peak connections, 3 million messages per month, and loads of features.

Create your free account