Message Persistence API for Android SDK

Message Persistence gives you real-time access to the history of messages published to PubNub. Each message is timestamped to the nearest 10 nanoseconds and stored across multiple availability zones in several geographic locations. You can encrypt stored messages with AES-256 so they are not readable on PubNub’s network. For details, see Message Persistence.

You control how long messages are stored through your account’s retention policy. Options include: 1 day, 7 days, 30 days, 3 months, 6 months, 1 year, or Unlimited.

You can retrieve the following:

  • Messages
  • Message reactions
  • Files (using the File Sharing API)

Fetch history

Requires Message Persistence

Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.

Fetch historical messages from one or multiple channels. Use includeMessageActions to include message reactions along with the messages.

You can control how messages are returned and in what order:

  • If you specify only the start parameter (without end), you receive messages older than the start timetoken.
  • If you specify only the end parameter (without start), you receive messages from that end timetoken and newer.
  • If you specify both start and end, you retrieve messages between those timetokens (inclusive of the end value).

You can receive up to 100 messages for a single channel, or 25 messages per channel when querying multiple channels (up to 500 channels). If more messages match the time range, make iterative calls and adjust the start timetoken to page through the results.

Method(s)

To run Fetch History, you can use the following method(s) in the Android SDK:

this.pubnub.fetchMessages()
.channels(List<String>)
.start(Long)
.end(Long)
.maximumPerChannel(Integer)
.includeMeta(Boolean)
.includeMessageActions(Boolean)
.includeMessageType(Boolean)
.includeUUID(Boolean)
* required
ParameterDescription
channels *
Type: List<String>
Default:
n/a
Channels to fetch history messages from (up to 500).
start
Type: Long
Default:
n/a
Timetoken delimiting the start of the time slice (exclusive) to pull messages from.
end
Type: Long
Default:
n/a
Timetoken delimiting the end of the time slice (inclusive) to pull messages from.
maximumPerChannel
Type: Integer
Default:
100 or 25
Number of historical messages to return per channel. Maximum is 100 for a single channel or 25 for multiple channels.
includeMeta
Type: Boolean
Default:
false
Whether to include message metadata in the response.
includeMessageActions
Type: Boolean
Default:
false
Retrieve history messages with message reactions. If true, limited to one channel only.
includeMessageType
Type: Boolean
Default:
true
Whether to include message type. If includeMessageActions is true, then 25 is the default and maximum.
includeUUID
Type: Boolean
Default:
true
Whether to include the publisher UUID.
async *
Type: PNCallback
Default:
n/a
PNCallback of type PNFetchMessagesResult.
Truncated response

If you fetch messages with message actions, the response may be truncated when internal limits are reached. If truncated, a more property is returned with additional parameters. Make iterative calls to history, adjusting the parameters to fetch more messages.

Sample code

Retrieve the last message on a channel:

pubnub.fetchMessages()
.channels(Arrays.asList("my_channel"))
.maximumPerChannel(25)
.includeMessageActions(true)
.includeMeta(true)
.includeMessageType(true)
.includeUUID(true)
.async(new PNCallback<PNFetchMessagesResult>() {
@Override
public void onResponse(PNFetchMessagesResult result, PNStatus status) {
if (!status.isError()) {
Map<String, List<PNFetchMessageItem>> channels = result.getChannels();
for (PNFetchMessageItem messageItem : channels.get("my_channel")) {
System.out.println(messageItem.getMessage());
System.out.println(messageItem.getMeta());
show all 36 lines

Returns

The fetchMessages() operation returns a list of PNFetchMessagesResult objects, each containing the following operations:

MethodDescription
getMessage()
Type: JsonElement
Message content.
getMeta()
Type: JsonElement
Message metadata if any, and if requested via includeMeta(true).
getTimetoken()
Type: Long
Publish timetoken.
getActionTimetoken()
Type: Long
Timestamp when the message reaction was created.
getActions()
Type: HashMap
Actions data of the message, if any, and if requested via includeMessageActions(true).
getMessageType()
Type: Integer
Message type 0 - message, 1 - signal, 2 - object, 3 - message reaction, 4 - files
getUuid()
Type: String
UUID of the publisher

Other examples

Paging history responses

package com.we.pubnubtest.utils;

import com.pubnub.api.models.consumer.history.PNFetchMessagesResult;

public abstract class CallbackSkeleton {

public CallbackSkeleton() {
}

public abstract void handleResponse(PNFetchMessagesResult result);

public abstract void finish();

}
package com.we.pubnubtest.utils;

import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.history.PNFetchMessagesResult;
import com.pubnub.api.models.consumer.pubsub.PNMessageResult;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class PubnubRecursiveHistoryFetcher {
private PubNub pubNub;
private String channels;
show all 66 lines

Fetch messages from multiple channels

pubNub.fetchMessages()
.channels(Arrays.asList("ch1", "ch2", "ch3"))
.async(new PNCallback<PNFetchMessagesResult>() {
@Override
public void onResponse(@Nullable final PNFetchMessagesResult result, @NotNull final PNStatus status) {
if (!status.isError()) {
final Map<String, List<PNFetchMessageItem>> channelToMessageItemsMap = result.getChannels();
final Set<String> channels = channelToMessageItemsMap.keySet();
for (final String channel : channels) {
List<PNFetchMessageItem> pnFetchMessageItems = channelToMessageItemsMap.get(channel);
for (final PNFetchMessageItem fetchMessageItem: pnFetchMessageItems) {
System.out.println(fetchMessageItem.getMessage());
System.out.println(fetchMessageItem.getMeta());
System.out.println(fetchMessageItem.getTimetoken());
}
show all 22 lines

Delete messages from history

Requires Message Persistence

Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.

Remove messages from the history of a specific channel.

Required setting

To accept delete-from-history requests, enable the Delete-From-History setting for your key in the Admin Portal and initialize the SDK with a secret key.

Method(s)

To Delete Messages from History you can use the following method(s) in the Android SDK.

this.pubnub.deleteMessages()
.channels(Array)
.start(Long)
.end(Long)
* required
ParameterDescription
channels *
Type: Array
Default:
n/a
Channels to delete messages from.
start
Type: Long
Default:
n/a
Timetoken delimiting the start of the time slice (inclusive) to delete messages from.
end
Type: Long
Default:
n/a
Timetoken delimiting the end of the time slice (exclusive) to delete messages from.
async *
Type: PNCallback
Default:
n/a
PNCallback of type PNDeleteMessagesResult.

Sample code

pubnub.deleteMessages()
.channels(Arrays.asList("channel_1", "channel_2"))
.start(1460693607379L)
.end(1460893617271L)
.async(new PNCallback<PNDeleteMessagesResult>() {
@Override
public void onResponse(PNDeleteMessagesResult result, PNStatus status) {
// The deleteMessages() method does not return actionable data, be sure to check the status
// object on the outcome of the operation by checking the status.isError().
}
});

Other examples

Delete specific message from history

To delete a specific message, pass the publish timetoken (received from a successful publish) in the End parameter and timetoken +/- 1 in the Start parameter. For example, if 15526611838554310 is the publish timetoken, pass 15526611838554309 in Start and 15526611838554310 in End parameters respectively as shown in the following code snippet.

pubnub.deleteMessages()
.channels(Arrays.asList("channel_1"))
.start(15526611838554309L)
.end(15526611838554310L)
.async(new PNCallback<PNDeleteMessagesResult>() {
@Override
public void onResponse(PNDeleteMessagesResult result, PNStatus status) {
// The deleteMessages() method does not return actionable data, be sure to check the status
// object on the outcome of the operation by checking the status.isError().
}
});

Message counts

Requires Message Persistence

Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.

Return the number of messages published on one or more channels since a given time. The count is the number of messages in history with a timetoken greater than or equal to the value passed in channelsTimetoken.

Unlimited message retention

For keys with unlimited message retention enabled, this method considers only messages published in the last 30 days.

Method(s)

You can use the following method(s) in the Android SDK:

this.pubnub.messageCounts()
.channels(Array)
.channelsTimetoken(Array)
* required
ParameterDescription
channels *
Type: Array
Default:
n/a
Channels to fetch the message count for.
channelsTimetoken *
Type: Array
Default:
n/a
List of timetokens, in the same order as the channels list. Specify a single timetoken to apply it to all channels. Otherwise, the list of timetokens must match the number of channels, or the function returns a PNStatus error.
async *
Type: PNCallback
Default:
n/a
PNCallback of type PNMessageCountResult.

Sample code

Long lastHourTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.HOURS.toMillis(1)) * 10000L;

pubnub.messageCounts()
.channels(Arrays.asList("news"))
.channelsTimetoken(Arrays.asList(lastHourTimetoken))
.async(new PNCallback<PNMessageCountResult>() {
@Override
public void onResponse(PNMessageCountResult result, PNStatus status) {
if (!status.isError()) {
for (Map.Entry<String, Long> messageCountEntry : result.getChannels().entrySet()) {
messageCountEntry.getKey(); // the channel name
messageCountEntry.getValue(); // number of messages for that channel
}
} else {
// Handle error accordingly.
show all 19 lines

Returns

The operation returns a PNMessageCountResult which contains the following properties:

MethodDescription
getChannels()
Type: Map<String, Long>
A map with values of Long for each channel. Channels without messages have a count of 0. Channels with 10,000 messages or more have a count of 10000.

Other examples

Retrieve count of messages using different timetokens for each channel

Long lastHourTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.HOURS.toMillis(1)) * 10000L;
Long lastDayTimetoken = (Calendar.getInstance().getTimeInMillis() - TimeUnit.DAYS.toMillis(1)) * 10000L;

pubnub.messageCounts()
.channels(Arrays.asList("news", "info"))
.channelsTimetoken(Arrays.asList(lastHourTimetoken, lastDayTimetoken))
.async(new PNCallback<PNMessageCountResult>() {
@Override
public void onResponse(PNMessageCountResult result, PNStatus status) {
if (!status.isError()) {
for (Map.Entry<String, Long> messageCountEntry : result.getChannels().entrySet()) {
messageCountEntry.getKey(); // the channel name
messageCountEntry.getValue(); // number of messages for that channel
}
} else {
show all 20 lines

History (deprecated)

Requires Message Persistence

Enable Message Persistence for your key in the Admin Portal. See how to enable add-on features.

Alternative method

This method is deprecated. Use fetch history instead.

Fetch historical messages for a channel.

You can control how messages are returned and in what order. For example, you can:

  • Search from the newest end of the timeline (default: reverse = false).
  • Search from the oldest end of the timeline by setting reverse to true.
  • Page through results by providing a start or end timetoken.
  • Retrieve a slice of the timeline by providing both a start and end timetoken.
  • Limit the number of messages using the count parameter.
Start & End parameter usage clarity

If you specify only start (without end), you receive messages older than and up to that start timetoken. If you specify only end (without start), you receive messages that match that end timetoken and newer. If you specify both start and end, you receive messages between those timetokens (inclusive of end). You still receive up to 100 messages even if more match. Make iterative calls to history, adjusting start, to page through the full result set.

Method(s)

To run History you can use the following method(s) in the Android SDK:

this.pubnub.history()
.channel(String)
.reverse(Boolean)
.includeTimetoken(Boolean)
.includeMeta(Boolean)
.start(Long)
.end(Long)
.count(Integer);
* required
ParameterDescription
channel *
Type: String
Default:
n/a
Channel to return history messages from.
reverse
Type: Boolean
Default:
false
Whether to traverse the timeline in reverse (oldest to newest) when set to true.
includeTimetoken
Type: Boolean
Default:
false
Whether event dates timetokens should be included in the response.
includeMeta
Type: Boolean
Default:
false
Whether to include message metadata within the response.
start
Type: Long
Default:
n/a
Timetoken delimiting the start of time slice (exclusive) to pull messages from.
end
Type: Long
Default:
n/a
Timetoken delimiting the end of time slice (inclusive) to pull messages from.
count
Type: Int
Default:
100
Number of historical messages to return.
async *
Type: PNCallback
Default:
n/a
PNCallback of type PNHistoryResult.
Using the reverse parameter

Messages are always returned sorted in ascending time direction from history regardless of reverse. The reverse direction matters when you have more than 100 (or count, if it's set) messages in the time interval, in which case reverse determines the end of the time interval from which it should start retrieving the messages.

Sample code

Retrieve the last 100 messages on a channel:

pubnub.history()
.channel("history_channel") // where to fetch history from
.count(100) // how many items to fetch
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {

}
});

Returns

The history() operation returns a PNHistoryResult which contains the following properties:

MethodDescription
getMessages()
Type: List<PNHistoryItemResult>
List of messages. See PNHistoryItemResult for more details.
getStartTimetoken()
Type: Long
Start timetoken.
getEndTimetoken()
Type: Long
End timetoken.

PNHistoryItemResult

MethodDescription
getTimetoken()
Type: Long
Timetoken of the message.
getEntry()
Type: JsonElement
Message.

Other examples

Use history() to retrieve the three oldest messages by retrieving from the time line in reverse

pubnub.history()
.channel("my_channel") // where to fetch history from
.count(3) // how many items to fetch
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {

}
});

Response

if (!status.isError()) {
for (PNHistoryItemResult pnHistoryItemResult: result.getMessages()) {
pnHistoryItemResult.getEntry(); // custom JSON structure for message
}
}

Use history() to retrieve messages newer than a given timetoken by paging from oldest message to newest message starting at a single point in time (exclusive)

pubnub.history()
.channel("my_channel") // where to fetch history from
.start(13847168620721752L) // first timestamp
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {

}
});
Response
if (!status.isError()) {
for (PNHistoryItemResult pnHistoryItemResult: result.getMessages()) {
pnHistoryItemResult.getEntry(); // custom JSON structure for message
}
}

Use history() to retrieve messages until a given timetoken by paging from newest message to oldest message until a specific end point in time (inclusive)

pubnub.history()
.channel("my_channel") // where to fetch history from
.count(100) // how many items to fetch
.start(-1) // first timestamp
.end(13847168819178600L) // last timestamp
.reverse(true) // should go in reverse?
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {

}
});
Response
[
["Pub3","Pub4","Pub5"],
13406746780720711,
13406746845892666
]

History paging example

Usage

You can call the method by passing 0 or a valid timetoken as the argument.

package com.pubnub.api;

import com.pubnub.api.v2.PNConfiguration;
import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.history.PNHistoryItemResult;
import com.pubnub.api.models.consumer.history.PNHistoryResult;

public class PubNubRecursiveHistoryFetcher {

private PubNub pubnub;

private static abstract class CallbackSkeleton {
public abstract void handleResponse(PNHistoryResult result);
show all 63 lines

Include timetoken in history response

pubnub.history()
.channel("history_channel") // where to fetch history from
.count(100) // how many items to fetch
.includeTimetoken(true) // include timetoken with each entry
.async(new PNCallback<PNHistoryResult>() {
@Override
public void onResponse(PNHistoryResult result, PNStatus status) {

}
});
Last updated on